{"record":{"id":"372102673d6fea83","repo":"gofiber/fiber","slug":"proxy-invalid-dial-address-q-w","errorCode":null,"errorMessage":"proxy: invalid dial address %q: %w","messagePattern":"proxy: invalid dial address %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/proxy/security.go","lineNumber":429,"sourceCode":"\t}\n\treturn nil\n}\n\n// newSSRFDialer returns a fasthttp DialFunc that resolves the target host\n// (with a bounded timeout), rejects the connection if any resolved\n// address falls in a blocked range, and then dials a validated address.\n// Performing the check at dial time — rather than only up front — defeats\n// DNS-rebinding attacks (the check/use gap) where a resolver returns a\n// public address during validation and a private one at connect time. It\n// is only installed when the active policy disallows private IPs.\n//\n//nolint:revive // dialDualStack mirrors fasthttp.HostClient.DialDualStack\nfunc newSSRFDialer(dialDualStack bool) fasthttp.DialFunc {\n\tdialer := &net.Dialer{Timeout: dnsLookupTimeout}\n\treturn func(addr string) (net.Conn, error) {\n\t\thost, port, err := net.SplitHostPort(addr)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"proxy: invalid dial address %q: %w\", addr, err)\n\t\t}\n\t\tips, err := resolveAndValidateHost(host)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn dialValidatedIPs(ips, host, port, dialDualStack, dialer.Dial)\n\t}\n}\n\n// resolveAndValidateHost looks up host (or treats it as an IP literal),\n// then enforces the SSRF blocklist on every returned address. A single\n// blocked answer fails the whole resolution so a mixed public/private\n// reply cannot slip past the guard.\nfunc resolveAndValidateHost(host string) ([]net.IP, error) {\n\tvar ips []net.IP\n\tif ip := net.ParseIP(host); ip != nil {\n\t\tips = []net.IP{ip}\n\t} else {","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/middleware/proxy/security.go#L411-L447","documentation":"In newSSRFDialer (the Balancer-installed dial-time guard), the inbound addr from fasthttp is split via net.SplitHostPort. If the address is not a valid host:port form, the split error is wrapped. This guard is purely structural — the address fasthttp hands the dialer should always be host:port, so this fires only on a misconfigured/buggy HostClient address.","triggerScenarios":"fasthttp invoked the dialer with an address missing a port (e.g. \"host\"), with an empty host (\":8080\"), with too many colons in a non-bracketed IPv6 literal (\"::1:8080\" instead of \"[::1]:8080\"), or with a non-numeric port.","commonSituations":"Balancer.Servers entry missing a port; a custom LBClient.Config.Client whose Addr is malformed; an IPv6 upstream entered without brackets; programmatic upstream construction that drops the port.","solutions":["Inspect the quoted addr in the message — it shows exactly what was passed to the dialer.","Ensure every Balancer.Servers and HostClient.Addr entry is host:port (or [ipv6]:port for IPv6).","Validate upstream addresses with net.SplitHostPort at config load and fail fast.","For IPv6 upstreams, always wrap the host in brackets: \"http://[::1]:8080\"."],"exampleFix":"// before: missing port on balancer entry\nbalancer.Servers = []string{\"http://upstream\"}\n\n// after: explicit port\nbalancer.Servers = []string{\"http://upstream:8080\"}","handlingStrategy":"validation","validationCode":"func validHostPort(addr string) error {\n  _, _, err := net.SplitHostPort(addr); return err\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always specify host:port in Balancer.Servers.","Bracket IPv6 literals: \"http://[::1]:8080\".","Validate upstreams with net.SplitHostPort at config load.","Inspect the quoted addr in the error to find the malformed entry."],"tags":["proxy","balancer","dialer","host-port","config"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}