micro/go-micro · error
push callback host %q resolves to a blocked address %s
Error message
push callback host %q resolves to a blocked address %s
What it means
This is the SSRF protection core of defaultPushURLPolicy: after resolving the callback host, each returned IP is checked with blockedPushIP, and this error is thrown if any address is loopback, private, link-local, multicast, or unspecified. It prevents push notifications from being aimed at internal infrastructure (localhost, metadata services, RFC1918 ranges).
Source
Thrown at gateway/a2a/pushsecurity.go:51
switch u.Scheme {
case "http", "https":
default:
return fmt.Errorf("push callback scheme %q not allowed (want http or https)", u.Scheme)
}
host := u.Hostname()
if host == "" {
return fmt.Errorf("push callback url has no host")
}
ips, err := resolvePushHost(host)
if err != nil {
return fmt.Errorf("push callback host %q: %w", host, err)
}
if len(ips) == 0 {
return fmt.Errorf("push callback host %q did not resolve", host)
}
for _, ip := range ips {
if blockedPushIP(ip) {
return fmt.Errorf("push callback host %q resolves to a blocked address %s", host, ip)
}
}
return nil
}
func resolvePushHost(host string) ([]net.IP, error) {
if ip := net.ParseIP(host); ip != nil {
return []net.IP{ip}, nil
}
return pushLookupIP(host)
}
// blockedPushIP reports whether ip is one an outbound push callback must not
// reach: loopback, private (RFC1918 / ULA), link-local (incl. 169.254.169.254
// cloud metadata), multicast, or the unspecified address.
func blockedPushIP(ip net.IP) bool {
return ip == nil ||
ip.IsLoopback() ||View on GitHub (pinned to 24529f1404)
Solutions
- Use a publicly routable callback host; expose the webhook receiver on a public address.
- If internal delivery is genuinely required, deploy an approved public proxy/relay in front of the internal service.
- Never accept raw user URLs for push callbacks without your own allowlist of webhook domains.
- If this fires unexpectedly on a legitimate host, inspect what the name resolves to (possible rebinding or misconfigured DNS).
Example fix
// before callback := "http://localhost:9090/a2a/push" // blocked // after callback := "https://push.example.com/a2a/push" // public, routable
Defensive patterns
Strategy: validation
Validate before calling
addrs, _ := net.LookupHost(host)
for _, a := range addrs {
ip := net.ParseIP(a)
if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsUnspecified() {
return fmt.Errorf("callback host %q resolves to private address %s", host, ip)
}
} Type guard
func isPublicIP(ip net.IP) bool {
return ip != nil && !ip.IsLoopback() && !ip.IsPrivate() &&
!ip.IsLinkLocalUnicast() && !ip.IsLinkLocalMulticast() && !ip.IsUnspecified()
} Prevention
- Never pass raw user-supplied webhook URLs to the push API without an allowlist
- Host webhook receivers on publicly routable endpoints
- Use an outbound relay/proxy if internal delivery is required
- Watch for DNS rebinding by re-checking resolution at registration time
When it happens
Trigger: Calling SetPushNotificationConfig with a callback URL whose host resolves to 127.0.0.1, ::1, 10.x/172.16.x/192.168.x, 169.254.x (including cloud metadata 169.254.169.254), 0.0.0.0, or a multicast address.
Common situations: Attacker-supplied webhook URL in a multi-tenant app attempting SSRF against the gateway; developer pointing callbacks at a locally running service in a production deployment; DNS rebinding where a public name resolves to a private IP.
Related errors
- push callback scheme %q not allowed (want http or https)
- push callback url has no host
- push callback host %q: %w
- push callback: refusing to connect to blocked address %s
- ai model is nil
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/08d128a4032cde16.
Report an issue: GitHub.