fix(core): restore cloud metadata IPs and link-local range in SSRF policy#36816
Conversation
Merging this PR will not alter performance
Comparing Footnotes
|
There was a problem hiding this comment.
Security Issues
- Denial of Service via unhandled exception in SSRF cloud-metadata range check
A new membership checkif addr in netmixes IPv6 addresses with an IPv4-only network tuple (169.254.0.0/16). In Python'sipaddressmodule, testing anIPv6Addressagainst anIPv4Networkraises aTypeError. This can cause unexpected exceptions (DoS) during URL validation for benign IPv6-resolving hostnames, allowing an attacker to submit such URLs and trigger failures in consumers that use these validators/transports.
Recommendations
- Guard membership checks by matching address family before testing (e.g., only test IPv4Address against IPv4Network, and IPv6Address against IPv6Network), or wrap the membership test in a try/except TypeError and continue on mismatch. Alternatively, maintain separate IPv4/IPv6 metadata network lists and select the appropriate one based on the address type.
| # Cloud metadata check — IP set *and* network ranges (e.g. 169.254.0.0/16). | ||
| # Independent of block_private_ips so that allow_private=True still blocks | ||
| # cloud metadata endpoints. | ||
| if policy.block_cloud_metadata: |
There was a problem hiding this comment.
The new cloud metadata network-range check can raise an unhandled exception for IPv6 addresses due to a cross-family membership test:
for net in _CLOUD_METADATA_NETWORKS: # type: ignore[assignment]
if addr in net:
return "cloud metadata endpoint"_CLOUD_METADATA_NETWORKS currently contains only an IPv4Network (169.254.0.0/16). When addr is an IPv6Address (e.g., a normal AAAA result for a public hostname), addr in net raises TypeError in the standard library ipaddress module. This can crash URL validation and any HTTP client using the SSRF transport, enabling a denial of service by supplying IPv6-resolving URLs.
Remediation: Only perform membership tests when the address family matches, or catch TypeError and continue. For example:
for net in _CLOUD_METADATA_NETWORKS:
if (isinstance(net, ipaddress.IPv4Network) and isinstance(addr, ipaddress.IPv4Address) and addr in net) \
or (isinstance(net, ipaddress.IPv6Network) and isinstance(addr, ipaddress.IPv6Address) and addr in net):
return "cloud metadata endpoint"Alternatively, maintain separate IPv4/IPv6 metadata network tuples and choose based on isinstance(addr, ipaddress.IPv4Address) / IPv6Address.
For more details, see the finding in Corridor.
Provide feedback: Reply with whether this is a valid vulnerability or false positive to help improve Corridor's accuracy.
Following #36768