ToolHive MCP Server SSRF via NAT64 IP Classification Bypass
First seen Sep 16, 2026 · Updated Sep 16, 2026
ToolHive's private-IP filtering utility fails to recognize IPv6 NAT64 translation prefixes, allowing attackers to encode private or link-local IPv4 addresses (like the cloud metadata IP 169.254.169.254) inside addresses that pass the public-IP check. On hosts behind a NAT64/DNS64 gateway, this lets an attacker probe internal network reachability through an MCP-related OAuth client metadata fetch path, though response bodies are not exposed, limiting impact to a reachability oracle rather than data theft.
Technical Analysis
The vulnerability lies in networking.IsPrivateIP, which omits the 64:ff9b::/96 and 64:ff9b:1::/48 NAT64 well-known prefixes from its private/loopback/link-local address blocklist. An external attacker can supply a malicious OAuth client_id URL that ToolHive's CIMDStorageDecorator.GetClient resolves via FetchClientMetadataDocument; if the resolved address is a NAT64-embedded private IP, the flawed classifier treats it as public and permits the outbound request. When the host sits behind a NAT64/DNS64 gateway, the gateway transparently translates the embedded address back to the real internal target (e.g., cloud metadata service or internal admin endpoints), enabling blind TCP/TLS reachability probing. Because the fetch enforces HTTPS with certificate validation and does not reflect response content back to the attacker, the crossable boundary is limited to confirming internal service existence/openness rather than exfiltrating credentials or secrets. The same defective IsPrivateIP logic is also shared by protectedDialerControl and validateHost, broadening the SSRF-adjacent exposure to other operator- or user-controlled destination paths within ToolHive, though the webhook client is unaffected since it uses a different IP guard.
Affected Systems
ToolHive; protocols: MCP, OAuth
Detection Signatures
- Outbound requests to IPv6 addresses matching 64:ff9b::/96 or 64:ff9b:1::/48 prefixes
- Unexpected OAuth client_id URLs resolving to NAT64-embedded IPv4 loopback/link-local/private ranges (e.g., embedding 169.254.169.254 or 10.0.0.0/8, 127.0.0.0/8, 192.168.0.0/16)
- Repeated CIMD/FetchClientMetadataDocument calls to varying internal-looking targets consistent with reachability scanning
- HTTP client logs showing successful TLS handshakes to NAT64-translated addresses that should have been blocked by egress filtering
Remediation Steps
- 1
Upgrade ToolHive
Update to ToolHive version 0.29.1 or later, which fixes the IsPrivateIP classification to include NAT64 well-known prefixes.
- 2
Harden IP validation logic
Ensure any custom or forked IP classification utilities explicitly decode and check NAT64-embedded IPv4 addresses against private/loopback/link-local ranges, not just the outer IPv6 address.
- 3
Restrict NAT64/DNS64 exposure
Avoid placing ToolHive hosts behind NAT64/DNS64 gateways where not operationally necessary, or apply network-level egress controls that block outbound connections to the 64:ff9b::/96 and 64:ff9b:1::/48 ranges.
- 4
Apply defense-in-depth network segmentation
Ensure internal metadata services (e.g., cloud instance metadata endpoints) require additional authentication (e.g., IMDSv2) so that reachability alone does not enable further compromise.
- 5
Audit shared validation code paths
Review protectedDialerControl and validateHost usages for the same flawed classification logic and apply consistent fixes across all consumers.
CVE / Advisory IDs
Industries Most Exposed
Respond to this threat
Pro subscribers get a full AI-generated incident-response playbook for this threat — detection, containment, eradication, and recovery steps — plus an unlimited AI Threat Advisor for questions about your environment.