Summary
WebhookApprover.ValidateEndpoint (added in #3363) is advertised as an SSRF control, but its blocklist is partial. It blocks cloud metadata IPs and link-local ranges, but does not block:
localhost / 127.0.0.0/8 (loopback)
- RFC 1918 private ranges (
10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
- IPv6 loopback (
::1) and unique-local (fc00::/7)
- DNS rebinding (a hostname that resolves to a blocked address at request time, since validation and the actual request can resolve separately)
Because the webhook endpoint is operator-configured, the immediate risk is low. But the method presents itself as a security boundary, so the gap is worth closing so operators do not over-trust it.
Context
Proposed fix
- Extend the blocklist to loopback, all RFC 1918 / IPv6 unique-local ranges, and
0.0.0.0.
- Resolve the host and validate every resolved IP, then pin the connection to a validated address (or re-validate on connect) to defeat DNS rebinding.
- Add tests covering loopback, a private-range host, and a rebinding-style host that resolves to a blocked IP.
- Until the guard is comprehensive, document in the
WebhookApprover XML docs exactly which ranges are and are not blocked, so it is not mistaken for a complete SSRF defense.
Acceptance
ValidateEndpoint rejects loopback, private, and IPv6 unique-local targets.
- Connection binds to a validated resolved address, or re-validates at connect.
- Tests cover the above, including a rebinding case.
Summary
WebhookApprover.ValidateEndpoint(added in #3363) is advertised as an SSRF control, but its blocklist is partial. It blocks cloud metadata IPs and link-local ranges, but does not block:localhost/127.0.0.0/8(loopback)10.0.0.0/8,172.16.0.0/12,192.168.0.0/16)::1) and unique-local (fc00::/7)Because the webhook endpoint is operator-configured, the immediate risk is low. But the method presents itself as a security boundary, so the gap is worth closing so operators do not over-trust it.
Context
agent-governance-dotnet/.../WebhookApprover.cs,ValidateEndpoint.Proposed fix
0.0.0.0.WebhookApproverXML docs exactly which ranges are and are not blocked, so it is not mistaken for a complete SSRF defense.Acceptance
ValidateEndpointrejects loopback, private, and IPv6 unique-local targets.