P1: blocked networks config + SSRF gaps (CGNAT, benchmark, NAT64 ranges not blocked) #67
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Verified against
mainat61f42e6. This is the "implement blocked networks configuration to extend SSRF protection" P1 item inTODO.md; confirmed genuinely still missing — there is no such config key and no CIDR list anywhere.The existing protection is sound in structure:
validateURL(internal/httpfetcher/httpfetcher.go:322-331) resolves and checks, andssrfSafeDialer(:412-441) resolves again and re-checks immediately before dialing, so the DNS-rebinding window is correctly closed at the dialer — that part is good and should not be regressed.The gap is coverage of
isPrivateIP(:366-409). It relies on a hardcoded list and does not appear to cover:100.64.0.0/10— CGNAT / carrier-grade NAT, routinely used for internal infrastructure192.0.0.0/24— IETF protocol assignments198.18.0.0/15— benchmark/test range64:ff9b::/96— NAT64, which maps straight back onto IPv4 private spaceUncertain, verify before changing: IPv4-mapped IPv6 (
::ffff:10.0.0.1) may already be handled, because Go'sip.IsPrivate()callsTo4()internally. Confirm with a test rather than assuming in either direction.Cloud metadata endpoints (
169.254.169.254) fall under link-local — confirm that is actually covered, since it is the single highest-value SSRF target in any deployment on a cloud provider.Definition of done
blocked_networks(or similarly named, following the descriptive-naming rule) config key accepting a list of CIDRs, merged with the built-in defaults rather than replacing them. Strict parsing: an invalid CIDR aborts startup naming the key and the offending value, per repo policy.ssrfSafeDialer(the authoritative check), not only invalidateURL, so the rebinding protection is preserved.::ffff:10.0.0.1,169.254.169.254, and a positive case proving ordinary public addresses still resolve and dial.blocked_networksentry is actually enforced by the dialer.make checkgreen.Related
Redirect-based SSRF (the
CheckRedirectvalidator athttpfetcher.go:133-143) is currently untested — covered in the separate httpfetcher test-coverage issue, but worth a glance while in this code.