proxy-addr CVE-2026-90711: IPv4-mapped IPv6 can erase the trusted proxy boundary
proxy-addr is a small Node.js package that decides which network hops are trusted proxies. Its output feeds req.ip and req.ips in Express. That makes it part of the identity path for IP allowlists, rate limiting, geolocation, and audit logs.
CVE-2026-90711 affects versions 1.1.0 through 2.0.7. The problem appears when an application configures an IPv4 trust subnet using IPv4-mapped IPv6 notation with an IPv4-sized prefix, such as ::ffff:10.0.0.0/8. The correct notation for that block is ::ffff:10.0.0.0/104. The package accepts the short form and compiles a match that covers every IPv4 address instead of only the intended subnet.
The failure is quiet. Configuration validation accepts the value. The application starts normally. The resulting trust decision is simply broader than the operator intended.
Why this becomes spoofing
Reverse proxies append client addresses to X-Forwarded-For. An application should trust that header only when the immediate peer is a known proxy and only for the correct number of hops. proxy-addr performs that evaluation.
If every address is treated as a trusted proxy, an unauthenticated client can supply its own X-Forwarded-For value. Express then reports that value as the client address. Any control that relies on req.ip sees the attacker's chosen string rather than the connection peer.
This does not magically bypass an application password. It bypasses controls that assume the address is trustworthy. Examples include admin routes restricted by source IP, rate limits keyed by address, geolocation policies, audit enrichment, and allowlists for webhook senders. The impact depends on what the application does with the address.
Audit trust-proxy configuration
Search source code, deployment manifests, and environment variables for Express trust proxy settings. Look for IPv6 values containing an IPv4-mapped prefix and a short prefix length. A valid mapped IPv4 subnet needs the mapped marker in its prefix calculation. Plain IPv4 notation is usually easier to review: 10.0.0.0/8.
Do not assume a reverse proxy makes the configuration safe. Check how many proxy hops exist. If an application accepts X-Forwarded-For from the internet before its own trusted proxy, the attacker can inject a value even when the trust list is correct.
Review code that derives authorization or rate limits from req.ip. A user ID, token, or signed device identity is a stronger basis for protected actions. IP restrictions should be defense in depth, not the only gate on a sensitive route.
Upgrade and add a failure test
Upgrade proxy-addr to 2.0.8 or later, or update the framework that bundles it. Then inspect the resolved dependency version. Applications often list Express as the direct dependency and never notice that proxy-addr is pinned by a lockfile.
Add a test for address parsing. Configure a trust subnet and send a request with a spoofed X-Forwarded-For value from a client that should not be trusted. Assert that req.ip reflects the actual peer or the expected trusted-proxy result. Repeat with a legitimate proxy hop.
Test IPv4, IPv4-mapped IPv6, and native IPv6. A correct result for one address family does not prove the other. Keep the test in the application suite so a future dependency update cannot silently restore the bug.
Check the audit trail
If the configuration existed before the patch, review logs for addresses that could not have belonged to the actual connection peer. Look for administrative actions, password resets, webhook calls, or rate-limit decisions tied to an address that appears only in a forwarded header.
The patch fixes the library's parsing and matching behavior. It does not repair authorization logic that trusted req.ip too much. Treat the dependency update and the application review as separate controls.
Top comments (0)