• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stacklok / toolhive / 26950483544

04 Jun 2026 12:02PM UTC coverage: 65.868%. Remained the same
26950483544

push

github

web-flow
Merge commit from fork

* Add NAT64 prefixes to IsPrivateIP SSRF guard

The hand-rolled private/reserved IP guard in pkg/networking/utilities.go did
not recognise the IPv6 NAT64 translation prefixes 64:ff9b::/96 (RFC 6052) and
64:ff9b:1::/48 (RFC 8215). A NAT64 address such as 64:ff9b:1::a9fe:a9fe is the
encoding of 169.254.169.254 (the cloud metadata endpoint) but is a syntactically
global-unicast IPv6 address, so IsPrivateIP returned false and the connection
was allowed. Behind a NAT64/DNS64 gateway this enabled SSRF to internal and
link-local services (including IMDS) via the CIMD authorization-server fetch
path and the webhook/remote HTTP client.

IsPrivateIP now detects NAT64-prefixed addresses, extracts the embedded IPv4
(low 32 bits), and re-evaluates it with the existing IPv4 private/reserved
checks. NAT64 addresses that embed a genuinely public IPv4 remain allowed, so
legitimate NAT64 egress is not over-blocked.

* Harden NAT64 /48 decoding and add SSRF tests

The initial fix always read the embedded IPv4 from the low 32 bits.
That is correct for the well-known 64:ff9b::/96 and the 64:ff9b:1::/96
sub-prefix, but the RFC 8215 local-use range is a /48 that operators may
subdivide with a shorter NAT64 prefix, placing the embedded IPv4 outside
the low 32 bits. Decoding the low 32 bits there could read attacker-chosen
suffix bytes and misclassify an internal target as public — a
false-negative SSRF bypass.

Limit low-32-bit decoding to the two /96 prefixes and block the remainder
of 64:ff9b:1::/48 wholesale, so undecodable NAT64 addresses fail closed.
Add NAT64 coverage (private and public embeddings, plus the non-/96
local-use case) to TestIsPrivateIP and TestAddressReferencesPrivateIp,
which the initial change asserted but did not commit.

Behavior change: addresses in 64:ff9b:1::/48 but outside 64:ff9b:1::/96
are now classified as private even when their low 32 bits embed a public
IPv4. This affects only deployments that use a non-/96 NAT64 pre... (continued)

27 of 28 new or added lines in 1 file covered. (96.43%)

13 existing lines in 5 files now uncovered.

66436 of 100862 relevant lines covered (65.87%)

61.49 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.44
/pkg/transport/proxy/httpsse/http_proxy.go


Source Not Available

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc