Skip to content

ZBBS-WORK-394: request_log takes the last X-Forwarded-For hop, not the first#232

Merged
jeffdafoe merged 1 commit into
mainfrom
zbbs-work-394-request-log-xff-last-hop
Jun 10, 2026
Merged

ZBBS-WORK-394: request_log takes the last X-Forwarded-For hop, not the first#232
jeffdafoe merged 1 commit into
mainfrom
zbbs-work-394-request-log-xff-last-hop

Conversation

@jeffdafoe

Copy link
Copy Markdown
Owner

Problem

The Recent API Activity panel logged today's ~1,640-request scanner wordlist burst as source 127.0.0.1 — the scanner sent X-Forwarded-For: 127.0.0.1 (localhost-trust probe) and the middleware takes the first XFF entry, which is client-controlled. nginx ($proxy_add_x_forwarded_for) appends the address it actually saw after client-supplied entries, so the last hop is the trustworthy one in our exactly-one-proxy deployment.

Display-integrity only — verified nothing in the app makes trust decisions off this field.

Fix

Take the last XFF hop; junk/missing header falls back to req.ip. Spoofed list → real IP; single hop → unchanged; direct local connection → socket address.

code_review: no blocking issues. Its optional array-header guard was deliberately skipped — Node joins duplicate headers into a single string for all non-set-cookie headers, so string-or-undefined is the platform contract.

— Work

🤖 Generated with Claude Code

…e first

The first XFF entry is client-controlled: nginx appends the address it
actually saw after any client-supplied entries, so a scanner sending
'X-Forwarded-For: 127.0.0.1' (localhost-trust probe) was logged as
127.0.0.1 in the admin Recent API Activity panel (observed 2026-06-10,
~1,640-request wordlist burst). We sit exactly one trusted proxy deep,
so the last entry is always the real peer. Display-only fix — nothing
in the app makes trust decisions off this field.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jeffdafoe jeffdafoe merged commit e4e18e7 into main Jun 10, 2026
@jeffdafoe jeffdafoe deleted the zbbs-work-394-request-log-xff-last-hop branch June 10, 2026 21:01
jeffdafoe added a commit that referenced this pull request Jun 16, 2026
…e first (#232)

The first XFF entry is client-controlled: nginx appends the address it
actually saw after any client-supplied entries, so a scanner sending
'X-Forwarded-For: 127.0.0.1' (localhost-trust probe) was logged as
127.0.0.1 in the admin Recent API Activity panel (observed 2026-06-10,
~1,640-request wordlist burst). We sit exactly one trusted proxy deep,
so the last entry is always the real peer. Display-only fix — nothing
in the app makes trust decisions off this field.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant