v0.8.29 — SSRF egress guard (CVE-2026-47390)
Added
feat(guard): deny-by-default SSRF egress guard for the alternate-encoding / rebinding bypass class (CVE-2026-47390)
Closes the SSRF-protection-bypass class (CWE-918, OWASP ASI02): an egress filter that validates the literal hostname string of an outbound URL — instead of the resolved IP — is bypassed by encoding loopback / link-local / cloud-metadata in a form ipaddress rejects but the HTTP client connects to, or by DNS rebinding.
SSRFEgressGuard(ssrf_egress_guard.py) reduces every target to its canonical IP(s) — decoding127.1/ decimal2130706433/ octal0177.0.0.1/ hex0x7f000001/0.0.0.0/ IPv6::1/::ffff:127.0.0.1/0:0:0:0:0:0:0:1viasocket.inet_aton, and resolving hostnames at check time so a rebind to loopback/metadata is caught at connect time — and fails closed on any loopback / link-local (incl.169.254.169.254IMDS) / metadata / unspecified / RFC1918 range not onallow_internal_hosts. 3-lineexplainaudit trace (rule / resolved IP / encoding) on every denial. Composes with the v0.5.5network.is_blocked_ipv6_rangeset. Never opens a socket.- New
SSRFEgressDecision/SSRFEgressVerdict/SSRFEgressBlocked. policy_presets.ssrf_egress_guard_defaults(allow_internal_hosts=…)— STANDARD egress posture (preset_id=ssrf_egress_guard,severity=high,owasp=ASI02,cwe=(CWE-918,),cves=(CVE-2026-47390,)).- 34 tests; built-wheel smoke confirms
http://0x7f000001/andhttp://169.254.169.254/are denied. Pydantic-only core, no new runtime deps. (#97)