fix(authz): judge the IP allow/deny list by the connection unless a t… - #15038
Merged
diegosouzapw merged 1 commit intoSep 29, 2026
Conversation
…rusted proxy fronts it The server stamps every request with the socket peer and marks it as proxied when X-Forwarded-For or X-Real-IP is present. For a proxied request the IP filter drops the socket peer and takes the client address from the forwarding headers. Any direct client can write those headers, so a blacklisted address could send `X-Forwarded-For: <clean address>` and be let through, and an address outside the whitelist could claim one that is on it. Only treat the two headers as a proxy signal when the connection comes from this host, a private-network address or a Cloudflare edge, the same peers the loopback and LAN checks already recognise. From any other address the request is judged by its own peer address. CF-Connecting-IP was already limited to Cloudflare edges as a marker. Behind a trusted proxy the client address was still whatever came first. The server now works it out where the socket is known and stamps it, token protected like the peer, for the filter to use: a Cloudflare edge's CF-Connecting-IP (a proxy that is not Cloudflare no longer gets to have it believed), else the right-most X-Forwarded-For entry that is not itself a trusted proxy, since a proxy appends to what the client sent and the entries before its own are the client's, else X-Real-IP. A header holding no usable address leaves the peer as the client, instead of judging "unknown", which every list lets through. A reverse proxy on any other public address would now be judged as the client, which under a whitelist locks everybody out. Such a proxy is named in the new OMNIROUTE_TRUSTED_PROXIES (IPs or CIDR ranges), the same idea as the existing OMNIROUTE_TRUST_PROXY but for the peer address. Loopback, private-network and Cloudflare peers stay trusted without it. A client that sits on a private address itself can still claim another address, which is the price of trusting that whole range without configuration. The peer stamp tests now cover the new marker and client stamp, and a parity test keeps the private ranges in step with the route guard's. Signed-off-by: Minxi Hou <houminxi@gmail.com>
diegosouzapw
merged commit Sep 29, 2026
1394706
into
diegosouzapw:release/v3.8.51
9 of 16 checks passed
4 of 5 tasks
diegosouzapw
pushed a commit
that referenced
this pull request
Sep 29, 2026
…quest (#15060) Maintainer rework: reconciled with #15038/#15040 on the tip — the wider forwarding-header set only sets the via-proxy marker from a peer that may be a proxy (hasProxyHopHeader && isTrustedProxyPeer). Loopback without headers stays local. 35 peer-stamp/route-guard/live-WS test files green. Board-validated with the rest of the batch on release/v3.8.51: typecheck:core, check:open-sse-typecheck, check-file-size, eslint on changed files, i18n:check-keys all green. Thank you @HouMinXi!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…rusted proxy fronts it
The server stamps every request with the socket peer and marks it as proxied when X-Forwarded-For or X-Real-IP is present. For a proxied request the IP filter drops the socket peer and takes the client address from the forwarding headers. Any direct client can write those headers, so a blacklisted address could send
X-Forwarded-For: <clean address>and be let through, and an address outside the whitelist could claim one that is on it.Only treat the two headers as a proxy signal when the connection comes from this host, a private-network address or a Cloudflare edge, the same peers the loopback and LAN checks already recognise. From any other address the request is judged by its own peer address. CF-Connecting-IP was already limited to Cloudflare edges as a marker.
Behind a trusted proxy the client address was still whatever came first. The server now works it out where the socket is known and stamps it, token protected like the peer, for the filter to use: a Cloudflare edge's CF-Connecting-IP (a proxy that is not Cloudflare no longer gets to have it believed), else the right-most X-Forwarded-For entry that is not itself a trusted proxy, since a proxy appends to what the client sent and the entries before its own are the client's, else X-Real-IP. A header holding no usable address leaves the peer as the client, instead of judging "unknown", which every list lets through.
A reverse proxy on any other public address would now be judged as the client, which under a whitelist locks everybody out. Such a proxy is named in the new OMNIROUTE_TRUSTED_PROXIES (IPs or CIDR ranges), the same idea as the existing OMNIROUTE_TRUST_PROXY but for the peer address. Loopback, private-network and Cloudflare peers stay trusted without it. A client that sits on a private address itself can still claim another address, which is the price of trusting that whole range without configuration. The peer stamp tests now cover the new marker and client stamp, and a parity test keeps the private ranges in step with the route guard's.
Summary
Related Issues
Validation
Choose the change type and focused loop from the
Contribution Golden Path. The full unit suite,
Vitest, the 60% coverage gate, and the production build all run in CI on this PR (#8329):
npm run lintTests Added Or Updated
Coverage Notes
src/,open-sse/,electron/, orbin/, explain which tests cover the change.Reviewer Notes