Skip to content

SSRF validation accepts RFC 6598 CGNAT (100.64.0.0/10), which AdCP 3.1.1 requires blocking #973

Description

@KonstantinMirin

Summary

adcp.signing.resolve_and_validate_host accepts destinations in 100.64.0.0/10. AdCP 3.1.1 lists that range explicitly in the reserved-range deny list a fetcher MUST apply before any outbound fetch to a counterparty-controlled URL.

Spec: dist/docs/3.1.0/building/by-layer/L1/security.mdx, "Webhook URL validation (SSRF)", step 2 — "IPv4: RFC 1918 (...), RFC 6598 CGNAT (100.64.0.0/10), loopback (...)".

Cause

The validator classifies reserved addresses with Python ipaddress flags:

ip.is_private or ip.is_loopback or ip.is_link_local
or ip.is_multicast or ip.is_reserved or ip.is_unspecified

is_private is False across 100.64.0.0/10 — RFC 6598 designates shared address space, not private space, so Python does not classify it. No other flag covers it either.

Reproduce

from unittest.mock import patch
from adcp.signing import resolve_and_validate_host

with patch("adcp.signing.jwks.socket.getaddrinfo",
           return_value=[(2, 1, 6, "", ("100.64.0.1", 0))]):
    print(resolve_and_validate_host("https://buyer-supplied.example/hook"))
# ("buyer-supplied.example", "100.64.0.1", 443)  -- accepted

Impact

CGNAT space is routable inside carrier networks and is commonly used by container/overlay networks, so a buyer-supplied push_notification_config.url or jwks_uri resolving there reaches an operator internal address. It is pre-auth-reachable on the JWKS path.

Partially masked today: Alibaba metadata 100.100.100.200 sits inside this range and is caught by name via BLOCKED_METADATA_IPS. Every other address in the /10 is reachable.

Also affected

192.88.99.0/24 (RFC 7526 deprecated 6to4 relay anycast) falls through the same flag set. Traffic there is tunnelled by whichever relay answers, so the destination is unattributable.

Fix

PR follows: adds an explicit _EXTRA_BLOCKED_NETWORKS tuple for the ranges the flags miss, behind the existing allow_private gate.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions