mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-10-25 22:10:25 +00:00
fc1f4e6181
* fix(server): resolve the client from the right-most untrusted X-Forwarded-For hop (BUG-3323) From a trusted peer, TrustedProxyRealIP took X-Real-IP first and otherwise the LEFTMOST X-Forwarded-For entry. On an appending proxy chain both are client-controlled: the leftmost entry is whatever the client sent, and a proxy that only appends to X-Forwarded-For (Azure Application Gateway, many ingress controllers) passes a client's X-Real-IP through. Any client behind such a proxy chose the address pad used for per-IP rate limits, 2FA challenge binding, session IP checks and audit. Now X-Forwarded-For wins when present, walked right to left, skipping hops inside PAD_TRUSTED_PROXIES, taking the first address outside them (nginx real_ip_recursive). ip:port entries are read as their address; an unparseable entry stops the walk. X-Real-IP is used only when there is no X-Forwarded-For. Cloud is unaffected: its router appends the resolved client, which is the right-most hop. Claude-Session: https://claude.ai/code/session_01H63zaWhkb5pAafx2WGjrVC * fix(server): read every X-Forwarded-For field, and document the append requirement (BUG-3323 review) Codex round 1, P2: Header.Get read only the first X-Forwarded-For field, so a proxy appending its hop as a second field left the client in control. All fields are now joined in order before the walk. The other P2 (a proxy that sets X-Real-IP but passes a client XFF through unchanged) is the cost of preferring XFF; the deployment guide now states that every trusted proxy must append to X-Forwarded-For. Claude-Session: https://claude.ai/code/session_01H63zaWhkb5pAafx2WGjrVC