ory/hydra · error
key %s validation is failing
Error message
key %s validation is failing
What it means
AreAllAssociatedIPsAllowed validates a map of key -> IP/hostname/URL pairs concurrently with an errgroup. If any single pair fails IsAssociatedIPAllowed (e.g. the address is a non-permitted destination or DNS resolution fails), that error is wrapped as 'key <key> validation is failing' and returned, identifying which entry in the map was rejected.
Source
Thrown at oryx/ipx/ip_validator.go:34
"github.com/pkg/errors"
)
// IsAssociatedIPAllowedWhenSet is a wrapper for IsAssociatedIPAllowed which returns valid
// when ipOrHostnameOrURL is empty.
func IsAssociatedIPAllowedWhenSet(ctx context.Context, ipOrHostnameOrURL string) error {
if ipOrHostnameOrURL == "" {
return nil
}
return IsAssociatedIPAllowed(ctx, ipOrHostnameOrURL)
}
// AreAllAssociatedIPsAllowed fails if one of the pairs is failing.
func AreAllAssociatedIPsAllowed(ctx context.Context, pairs map[string]string) error {
g, ctx := errgroup.WithContext(ctx)
for key, ipOrHostnameOrURL := range pairs {
g.Go(func() error {
return errors.Wrapf(IsAssociatedIPAllowed(ctx, ipOrHostnameOrURL), "key %s validation is failing", key)
})
}
return g.Wait()
}
// IsAssociatedIPAllowed returns nil for a domain (with NS lookup), IP, or IPv6 address if it
// does not resolve to a private IP subnet. This is a first level of defense against
// SSRF attacks by disallowing any domain or IP to resolve to a private network range.
//
// Please keep in mind that validations for domains is valid only when looking up.
// A malicious actor could easily update the DSN record post validation to point
// to an internal IP
func IsAssociatedIPAllowed(ctx context.Context, ipOrHostnameOrURL string) error {
ipOrHostname := ipOrHostnameOrURL
if parsed, err := url.ParseRequestURI(ipOrHostnameOrURL); err == nil {
ipOrHostname = parsed.Hostname()
}
View on GitHub (pinned to 4174065ffb)
Solutions
- Look at the wrapped inner error to see which check failed for that key
- Replace the offending value for that key with a public, resolvable IP/hostname
- If the endpoint is legitimately internal (dev environment), relax/adjust the IP allowlist configuration
- Verify DNS resolution for the hostname (dig/nslookup) if the failure is lookup-related
Example fix
// before
pairs := map[string]string{"webhook": "http://127.0.0.1:9090/callback"}
err := ipx.AreAllAssociatedIPsAllowed(ctx, pairs) // fails: loopback not permitted
// after
pairs := map[string]string{"webhook": "https://api.example.com/callback"}
err := ipx.AreAllAssociatedIPsAllowed(ctx, pairs) Defensive patterns
Strategy: validation
Validate before calling
for key, addr := range pairs {
if net.ParseIP(addr) == nil {
if _, err := net.LookupHost(addr); err != nil {
return fmt.Errorf("key %s: cannot resolve %q", key, addr)
}
}
} Try / catch
if err := ipx.AreAllAssociatedIPsAllowed(ctx, pairs); err != nil {
var keyErr *fmt.WrapError
if errors.As(err, &keyErr) {
log.Printf("failed pair identified: %v", err) // message names the key
}
} Prevention
- Pre-resolve all hostnames before validation to catch DNS issues early
- Reject loopback/private addresses in your own config validation
- Keep a curated allowlist of public endpoints for webhooks/callbacks
- Log the full wrapped error — it names the offending key
When it happens
Trigger: Calling AreAllAssociatedIPsAllowed with a map where at least one value is an IP/hostname/URL that fails IsAssociatedIPAllowed — e.g. points to a private/loopback address when such destinations are forbidden, or a hostname whose NS lookup fails.
Common situations: Validating claimed redirect/allowed endpoints (e.g. courier SMTP or webhook configuration) where one configured host resolves to localhost or an internal IP; typo'd hostnames that fail DNS; SSRF-protection rejecting internal endpoints in dev/staging configs.
Related errors
- DNS lookup timed out
- no route to host
- ip %s is not a permitted destination
- Token is expired
- Token used before issued
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/eb316d3718e628a9.
Report an issue: GitHub.