micro/go-micro · error

push callback: refusing to connect to blocked address %s

Error message

push callback: refusing to connect to blocked address %s

What it means

pushDialControl rejects dialing addresses whose parsed IP is in the blocked set (private, loopback, link-local ranges per blockedPushIP). This SSRF protection prevents push notifications from being used to reach internal infrastructure. The error is raised at connect time when the callback target resolves to a forbidden address.

Source

Thrown at gateway/a2a/pushsecurity.go:91

		ip.IsInterfaceLocalMulticast() ||
		ip.IsMulticast() ||
		ip.IsUnspecified()
}

// pushDialControl runs after DNS resolution, immediately before connect, on the
// resolved address — so it blocks a host that passed URL validation but was
// rebound to an internal IP (DNS rebinding).
func pushDialControl(_, address string, _ syscall.RawConn) error {
	host, _, err := net.SplitHostPort(address)
	if err != nil {
		return err
	}
	ip := net.ParseIP(host)
	if ip == nil {
		return fmt.Errorf("push callback: cannot parse dial address %q", address)
	}
	if blockedPushIP(ip) {
		return fmt.Errorf("push callback: refusing to connect to blocked address %s", ip)
	}
	return nil
}

// pushGuardClient is the HTTP client used for default-policy push delivery. Its
// dialer refuses connections to blocked addresses at connect time.
var pushGuardClient = &http.Client{
	Timeout: 10 * time.Second,
	Transport: &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		DialContext: (&net.Dialer{
			Timeout: 5 * time.Second,
			Control: pushDialControl,
		}).DialContext,
	},
}

// checkPushURL validates a callback URL against the dispatcher's effective

View on GitHub (pinned to 24529f1404)

Solutions

  1. Point the push callback at a public, non-blocked IP address.
  2. Expose the local receiver via a public tunnel/host and use that public address in the callback URL.
  3. If internal callbacks are intentionally required, configure a custom AllowPushURL policy / dial control that explicitly allows the specific internal range.

Example fix

// before
setPushConfig(task, "http://127.0.0.1:9090/push")
// after
setPushConfig(task, "https://push.example.com/push") // public address, not blocked
Defensive patterns

Strategy: validation

Validate before calling

u, _ := url.Parse(callbackURL)
ip := net.ParseIP(u.Hostname())
if ip != nil && (ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast()) {
    return fmt.Errorf("callback %s targets a blocked address", ip)
}

Type guard

func isPublicIP(rawURL string) bool {
    u, err := url.Parse(rawURL)
    if err != nil { return false }
    ip := net.ParseIP(u.Hostname())
    return ip != nil && !ip.IsLoopback() && !ip.IsPrivate() && !ip.IsLinkLocalUnicast()
}

Prevention

When it happens

Trigger: A push callback URL points at (or resolves to) a blocked IP such as 127.0.0.1, 10.x.x.x, 172.16.x.x, 192.168.x.x, or 169.254.169.254, and a push delivery attempt dials it under the default SSRF policy.

Common situations: Developers testing against a local push receiver on localhost; misconfigured callbacks pointing at internal cluster services; attackers supplying callback URLs targeting cloud metadata endpoints (169.254.169.254).

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/524f12a8d6aa8d42. Report an issue: GitHub.