Tencent/WeKnora · error
connection blocked: hostname %s is restricted
Error message
connection blocked: hostname %s is restricted
What it means
SSRFSafeDialContext blocked the connection because the hostname exactly matches an entry in the restrictedHostnames list. Names such as localhost or cloud metadata hostnames are denied at dial time as a second layer of defense behind URL validation. The comparison is case-insensitive (strings.ToLower), so casing tricks do not bypass it.
Source
Thrown at internal/utils/security.go:817
// ValidateURLForSSRF which skips isSSRFSafeURL for whitelisted hosts.
// NOTE: This intentionally relaxes DNS-rebinding protection for whitelisted
// hosts. Admins must ensure whitelisted domains are under their control.
if IsSystemProxy(addr) || IsSSRFWhitelisted(host) {
dialer := &net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}
return dialer.DialContext(ctx, network, addr)
}
if restrictedPorts[port] {
return nil, fmt.Errorf("connection blocked: port %s is restricted", port)
}
// Check if the host is a restricted hostname
hostLower := strings.ToLower(host)
for _, restricted := range restrictedHostnames {
if hostLower == restricted {
return nil, fmt.Errorf("connection blocked: hostname %s is restricted", host)
}
}
for _, suffix := range restrictedHostSuffixes {
if strings.HasSuffix(hostLower, suffix) {
return nil, fmt.Errorf("connection blocked: hostname suffix %s is restricted", suffix)
}
}
// Resolve the hostname once, validate every answer, and then dial one of
// those exact IPs. Dialing the original hostname here would make the
// standard dialer resolve it a second time, leaving a DNS-rebinding window
// between validation and connection establishment.
ips, err := net.DefaultResolver.LookupIPAddr(ctx, host)
if err != nil {
return nil, fmt.Errorf("DNS resolution failed for %s: %w", host, err)
}
if len(ips) == 0 {
return nil, fmt.Errorf("DNS resolution returned no addresses for %s", host)View on GitHub (pinned to 988cbb0330)
Solutions
- Dial the service using a non-restricted hostname or its routable public name instead of the restricted hostname.
- For trusted internal endpoints, register the host in the SSRF whitelist so dial-time checks are skipped for it.
- In tests, use a whitelisted test host or inject the whitelist before dialing rather than using "localhost".
- Confirm the exact restricted list in internal/utils/security.go and rename your service host if it collides accidentally.
Example fix
// before conn, err := utils.SSRFSafeDialContext(ctx, "tcp", "localhost:8080") // after conn, err := utils.SSRFSafeDialContext(ctx, "tcp", "api.internal.example.com:8080") // or add host to whitelist
Defensive patterns
Strategy: validation
Validate before calling
host, _, _ := net.SplitHostPort(addr)
h := strings.ToLower(host)
for _, restricted := range []string{"localhost" /* + restrictedHostnames list */} {
if h == restricted {
return fmt.Errorf("hostname %s is restricted; use the service's routable name or whitelist it", host)
}
} Try / catch
conn, err := utils.SSRFSafeDialContext(ctx, "tcp", addr)
if err != nil && strings.Contains(err.Error(), "hostname") && strings.Contains(err.Error(), "is restricted") {
return nil, fmt.Errorf("restricted destination hostname (configure whitelist if intended): %w", err)
} Prevention
- Use routable service names instead of localhost/metadata hostnames in configuration.
- Add trusted internal hosts to the SSRF whitelist during deployment setup.
- Never hardcode localhost endpoints in production code paths.
- Review hostnames against the restrictedHostnames list when onboarding new services.
When it happens
Trigger: Calling SSRFSafeDialContext / SSRFSafeGRPCDialer (directly or as http.Transport.DialContext) with addr whose host equals a restricted hostname like "localhost" or a metadata hostname, and the host is not whitelisted. TestSSRFSafeDialContextRejectsRestrictedPortAtFinalSink exercises the final-sink path where this fires.
Common situations: Pointing the SSRF-safe client at http://localhost:port for local development; legacy configs using "metadata" style hostnames; tests that dial the local test server without a whitelist entry.
Related errors
- connection blocked: port %s is restricted
- connection blocked: hostname suffix %s is restricted
- outbound request blocked by SSRF policy: %w
- invalid address %s: %w
- unsafe MinIO endpoint: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/3c021faf5d4fd1ab.
Report an issue: GitHub.