Block NAT64 and IPv4-compatible embedded addresses in load_web_page SSRF guard - #6486
Open
herdiyana256 wants to merge 3 commits into
Open
Block NAT64 and IPv4-compatible embedded addresses in load_web_page SSRF guard#6486herdiyana256 wants to merge 3 commits into
herdiyana256 wants to merge 3 commits into
Conversation
…SRF guard _is_blocked_address rejected any address that is not global, which correctly blocks IPv4 private/loopback/link-local literals and their IPv4-mapped IPv6 form. It did not block the NAT64 well-known prefix (64:ff9b::/96) or the deprecated IPv4-compatible form (::a.b.c.d): ipaddress classifies both as globally routable even though they embed an internal IPv4 address. On a NAT64-enabled network a request to 64:ff9b::169.254.169.254 is translated to the IPv4 link-local metadata endpoint, so the guard could be bypassed to reach internal or metadata addresses. Unwrap the embedded IPv4 address from these forms and re-check it, so a target is blocked when either the IPv6 address or its embedded IPv4 address is non-global. NAT64 to a genuinely public IPv4 (for example 64:ff9b::8.8.8.8) is still allowed.
rohityan
force-pushed
the
fix-load-web-page-nat64-ssrf
branch
from
July 27, 2026 21:24
602a5c7 to
4cc8fed
Compare
Collaborator
|
Hi @herdiyana256 , Thank you for your contribution! We appreciate you taking the time to submit this pull request. |
Author
|
Thanks @rohityan! Added unit tests in
All pass locally ( |
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.
load_web_page validates fetch targets through _is_blocked_address, which rejects any address that is not global. That correctly blocks IPv4 private, loopback, and link-local literals, hostnames that resolve to them, and the IPv4-mapped IPv6 form ::ffff:a.b.c.d.
It does not block two other IPv6 encodings that carry an internal IPv4 address. The NAT64 well-known prefix 64:ff9b::/96 (RFC 6052) and the deprecated IPv4-compatible form ::a.b.c.d both embed an IPv4 address in their low 32 bits, but the standard library classifies them as globally routable, so is_global is True and the guard allows them. As a result 64:ff9b::169.254.169.254 and ::169.254.169.254 pass the check, and the same holds for private and loopback ranges.
On a NAT64-enabled network (common in IPv6-only environments) a connection to 64:ff9b::169.254.169.254 is translated by the NAT64 gateway to the IPv4 link-local metadata endpoint 169.254.169.254, so an attacker who can influence the URL passed to the tool can reach cloud metadata or other internal services despite the guard. The target can also be delivered through DNS by publishing an AAAA record inside the prefix.
This change unwraps the embedded IPv4 address from the IPv4-mapped, NAT64 well-known, and IPv4-compatible forms and re-checks it, so a target is blocked when either the IPv6 address or its embedded IPv4 address is non-global. NAT64 to a genuinely public IPv4 such as 64:ff9b::8.8.8.8 is still allowed, and the existing load_web_page test suite continues to pass.