fix: prevent IPv4-mapped IPv6 trust subnets from matching all IPv4 (GHSA-jqcg-44mw-7w3h) - #117
Merged
Merged
Conversation
An IPv4-mapped IPv6 trust subnet with a short prefix, such as `::ffff:10.0.0.0/8`, compiled with all-zero leading bits and matched every IPv4 address instead of the block it named. This trusted any unauthenticated client as a proxy at hop 0, so proxyaddr() (and req.ip/req.ips in Express) returned the attacker-controlled X-Forwarded-For value, defeating IP-based access control, rate limiting, geolocation and audit logging. Port the upstream proxy-addr 2.0.8 remediation: - canonicalize IPv4-mapped candidates to IPv4 up front, so a mapped address cannot bypass the cross-family guard via the same-family path - an IPv6 trust subnet only spans IPv4 when it is a genuine IPv4-mapped subnet whose prefix covers the ::ffff: marker (range >= 96) - a native IPv6 candidate can no longer match an IPv4-mapped subnet Ref: GHSA-jqcg-44mw-7w3h / CVE-2026-90711
mcollina
requested review from
Eomm,
Fdawgs,
delvedor,
gurgunday and
ivan-tymoshenko
September 15, 2026 07:46
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.
Summary
Ports the upstream proxy-addr 2.0.8 remediation for GHSA-jqcg-44mw-7w3h / CVE-2026-90711 (severity critical, CVSS 9.1).
An IPv4-mapped IPv6 trust subnet with a short prefix (e.g.
::ffff:10.0.0.0/8) compiled with all-zero leading bits and matched every IPv4 address instead of the block it named. That trusted any unauthenticated client as a proxy at hop 0, soproxyaddr()— and thereforereq.ip/req.ipsin Express — returned the attacker-suppliedX-Forwarded-Forvalue, defeating IP-based access control, rate limiting, geolocation and audit logging.Repro (before fix)
After the fix this returns
1.1.1.1, and the correct spelling::ffff:10.0.0.0/104(or plain10.0.0.0/8) continues to behave correctly.Changes
index.js::ffff:marker (range ≥ 96); short prefixes like/8or::/1no longer match IPv4.test/base.test.js— regression tests for the short-prefix mapped subnet,::/1, and native-IPv6-vs-mapped-subnet cases for both the single and multi-subnet trust paths.The conversion was simplified to only produce an IPv4-mapped address because, after the up-front canonicalization, a cross-family IPv4 subnet is handled via the same-family path; this keeps the enforced 100% branch coverage intact.
Verification
npm test— 75 unit tests pass, 100% statement/branch/function/line coveragenpm run lint— cleannpm run test:typescript— passResolves the vulnerability in this fork (note: the advisory is filed against the upstream
proxy-addrpackage and does not enumerate this fork, but the vulnerable code was inherited).