screentinker/server/routes
ScreenTinker 45a6800621 fix: log real client IPs through Cloudflare instead of CF edge
Express's req.ip was resolving to a Cloudflare edge address (e.g.
172.70.x.x) for any request fronted by Cloudflare, because trust proxy
was set to '1' — that trusts the immediate hop, which IS Cloudflare.
All activity_log rows from API paths captured the proxy, not the
client. The WebSocket path was unaffected and recorded the real IP.

Two layers of defense:

1. trust proxy now lists Cloudflare's published v4 + v6 ranges plus
   loopback / linklocal / uniquelocal (config/cloudflareIps.js). With
   this list req.ip resolves to the original client when fronted by
   CF, and X-Forwarded-For from any non-trusted source is ignored —
   so the value can't be spoofed.

2. New getClientIp(req) helper in services/activity.js prefers the
   CF-Connecting-IP header but only honors it when the immediate TCP
   peer is itself a trusted address. Same gate as trust proxy, so a
   visitor who hits the origin directly with a forged header is
   logged at their real address.

Routed all five activity-log call sites (auth login success/failure,
admin password reset, generic activityLogger middleware, and the
in-memory rate-limiter key) through the helper.

Logging-only change. No schema changes. Existing rows are not
modified — fix applies to new entries going forward.

Verified locally:
- Bare loopback hit logs 127.0.0.1 (not a proxy address).
- Helper unit cases including an untrusted peer (203.0.113.7) sending
  a forged CF-Connecting-IP correctly fall back to the real peer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 15:26:37 -05:00
..
activity.js Initial open source release 2026-04-08 12:14:53 -05:00
assignments.js Fix 8 security findings from Phase 3 audit + device-detail banner refresh 2026-04-13 21:36:16 -05:00
auth.js fix: log real client IPs through Cloudflare instead of CF edge 2026-05-07 15:26:37 -05:00
content.js Security: fix IDORs, XSS, rate limits, SSRF validation 2026-04-28 14:37:18 -05:00
device-groups.js Video walls: free-form canvas editor, leader-driven sync, group dissolve, progress bars 2026-04-29 23:11:16 -05:00
devices.js Phase 3: playlist publish/draft state with auto-publish from device detail 2026-04-13 20:52:29 -05:00
folders.js Security: fix IDORs, XSS, rate limits, SSRF validation 2026-04-28 14:37:18 -05:00
kiosk.js Security: fix IDORs, XSS, rate limits, SSRF validation 2026-04-28 14:37:18 -05:00
layouts.js Security audit remediation: auth, IDOR, XSS, hardening 2026-04-11 22:48:07 -05:00
playlists.js Fix 8 security findings from Phase 3 audit + device-detail banner refresh 2026-04-13 21:36:16 -05:00
provisioning.js Initial open source release 2026-04-08 12:14:53 -05:00
reports.js Initial open source release 2026-04-08 12:14:53 -05:00
schedules.js Security: fix IDORs, XSS, rate limits, SSRF validation 2026-04-28 14:37:18 -05:00
status.js Add group-level scheduling, group playlist assignment, and persist audio unlock 2026-04-15 20:22:42 -05:00
stripe.js Security audit remediation: auth, IDOR, XSS, hardening 2026-04-11 22:48:07 -05:00
subscription.js Initial open source release 2026-04-08 12:14:53 -05:00
teams.js Security: fix IDORs, XSS, rate limits, SSRF validation 2026-04-28 14:37:18 -05:00
video-walls.js Video walls: free-form canvas editor, leader-driven sync, group dissolve, progress bars 2026-04-29 23:11:16 -05:00
white-label.js Initial open source release 2026-04-08 12:14:53 -05:00
widgets.js Admin password reset + widget visibility fix 2026-04-29 20:45:25 -05:00