Tencent/WeKnora · error
outbound request blocked by SSRF policy: %w
Error message
outbound request blocked by SSRF policy: %w
What it means
The request URL failed the library's SSRF policy check performed by validateURLForSSRFForOutbound before the request is handed to the base transport. The library blocks outbound requests to disallowed destinations (private/loopback/link-local IPs, restricted hosts, restricted ports, non-safe schemes) to prevent server-side request forgery. The wrapped cause (%w) explains exactly which rule was violated.
Source
Thrown at internal/utils/security.go:752
// SSRFValidatingRoundTripper enforces the URL policy for every outbound
// request, including URLs discovered at runtime by SDKs (for example OAuth
// metadata) that never passed through an application handler. Dial-time checks
// remain necessary to pin DNS answers and cover transports that cannot accept
// this wrapper directly.
type SSRFValidatingRoundTripper struct {
Base http.RoundTripper
}
func (t *SSRFValidatingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
if req == nil || req.URL == nil {
return nil, fmt.Errorf("outbound request blocked: request URL is required")
}
if t == nil || t.Base == nil {
return nil, fmt.Errorf("outbound request blocked: base transport is required")
}
if err := validateURLForSSRFForOutbound(req.URL.String()); err != nil {
return nil, fmt.Errorf("outbound request blocked by SSRF policy: %w", err)
}
return t.Base.RoundTrip(req)
}
// NewSSRFSafeHTTPClientWithTransport wraps a caller-supplied transport in an
// *http.Client carrying the given timeout and the SSRF-aware redirect policy.
// Pass a transport from NewSSRFSafeTransport (optionally shared across clients)
// to reuse a single connection pool while keeping per-client timeouts.
func NewSSRFSafeHTTPClientWithTransport(
config SSRFSafeHTTPClientConfig, transport http.RoundTripper,
) *http.Client {
if transport == nil {
transport = NewSSRFSafeTransport(config)
}
return &http.Client{
Timeout: config.Timeout,
Transport: &SSRFValidatingRoundTripper{Base: transport},
CheckRedirect: newSSRFCheckRedirect(config.MaxRedirects),View on GitHub (pinned to 988cbb0330)
Solutions
- Inspect the wrapped error (errors.Unwrap / %v of the chain) to see which SSRF rule fired, then change the target URL to a public, allowed host.
- If the destination is legitimately internal, add it to the SSRF whitelist mechanism provided by the library (whitelisted hosts bypass the checks) rather than disabling validation.
- For tests, point the request at the approved test host or inject a whitelist entry instead of using 127.0.0.1.
- Validate the URL yourself with ValidateURLForSSRF before building the request to get an earlier, clearer failure.
Example fix
// before
req, _ := http.NewRequest("GET", "http://169.254.169.254/latest/meta-data/", nil)
resp, err := client.Do(req) // blocked by SSRF policy
// after
if err := utils.ValidateURLForSSRF("https://api.example.com/v1/info"); err != nil { /* handle */ }
req, _ := http.NewRequest("GET", "https://api.example.com/v1/info", nil)
resp, err := client.Do(req) Defensive patterns
Strategy: validation
Validate before calling
if err := utils.ValidateURLForSSRF(targetURL); err != nil {
return fmt.Errorf("refusing to fetch %s: %w", targetURL, err)
}
req, _ := http.NewRequest("GET", targetURL, nil) Try / catch
resp, err := client.Do(req)
if err != nil {
var blocked *fmt.Errorf
if strings.Contains(err.Error(), "blocked by SSRF policy") {
// log the policy violation, do not retry — it will keep failing
return nil, fmt.Errorf("target rejected by SSRF policy: %w", err)
}
return nil, err
} Prevention
- Run ValidateURLForSSRF on any user-supplied URL before building the request.
- Never point the SSRF-safe client at localhost/private IPs in production or tests without whitelisting.
- Keep a whitelist for legitimate internal hosts instead of bypassing the guard.
- Log unwrapped policy errors to identify which SSRF rule fired.
When it happens
Trigger: RoundTrip (e.g. via an http.Client configured with SSRFValidatingRoundTripper) invoked with a request whose URL fails validateURLForSSRFForOutbound: pointing at 127.0.0.1/localhost, private RFC1918 ranges, metadata endpoints (169.254.169.254), file/non-http schemes, restricted ports, or a hostname that resolves to a blocked IP. TestSSRFValidatingRoundTripperUsesOutboundCache reaches this path whenever the URL is not policy-compliant.
Common situations: Calling internal microservice endpoints like http://localhost:8080 from behind the SSRF-safe client; fetching user-supplied URLs that target internal addresses; cloud-metadata lookups from inside the guarded code path; tests pointing at a local httptest server.
Related errors
- URL rejected: %w
- base_url SSRF validation failed: %w
- URL rejected for security reasons: %v
- docreader address failed SSRF validation: %w
- blocked by SSRF policy: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/defd43690cfb340c.
Report an issue: GitHub.