{"record":{"id":"2aeeae4382f2fb03","repo":"weaviate/weaviate","slug":"refusing-to-dial-internal-address-q","errorCode":null,"errorMessage":"refusing to dial internal address %q","messagePattern":"refusing to dial internal address %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"usecases/modulecomponents/base_client.go","lineNumber":62,"sourceCode":"\n\treturn &http.Client{\n\t\tTransport: &retryTransport{base: transport, timeout: timeout},\n\t\tCheckRedirect: func(req *http.Request, via []*http.Request) error {\n\t\t\treturn http.ErrUseLastResponse\n\t\t},\n\t}\n}\n\n// ssrfDialGuard blocks connections to internal addresses. address is the\n// resolved \"ip:port\", so a host that resolves to an internal IP is caught here\n// even if it slipped past ValidateBaseURL's string-level checks.\nfunc ssrfDialGuard(network, address string, c syscall.RawConn) error {\n\thost, _, err := net.SplitHostPort(address)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid dial address %q: %w\", address, err)\n\t}\n\tif ip := net.ParseIP(host); ip != nil && isDisallowedIP(ip) {\n\t\treturn fmt.Errorf(\"refusing to dial internal address %q\", address)\n\t}\n\treturn nil\n}\n","sourceCodeStart":44,"sourceCodeEnd":66,"githubUrl":"https://github.com/weaviate/weaviate/blob/75aa4b6d11f8818305aafd4440b4e32794f7ca04/usecases/modulecomponents/base_client.go#L44-L66","documentation":"ssrfDialGuard blocks outbound connections whose resolved IP is internal (loopback, private ranges, link-local, etc.) via isDisallowedIP. Because it inspects the resolved ip:port, DNS names that resolve to internal addresses are also caught, defending against SSRF even when string-level URL validation passed.","triggerScenarios":"The module client dials a host whose resolved IP is private/loopback/link-local — e.g. baseUrl set to localhost, 127.0.0.1, 10.x, 172.16-31.x, 192.168.x, 169.254.x, or a DNS name resolving to such an address.","commonSituations":"Local development pointing a vectorizer/generative module at localhost inference server; Kubernetes in-cluster service using cluster-internal IPs (cluster-local traffic blocked); DNS rebinding or misconfigured external hostname resolving to a private IP.","solutions":["Point the module baseUrl at a genuinely public, routable endpoint","If the internal endpoint is intentional (self-hosted inference), deploy it on a routable address or use the supported configuration to allow it","Check DNS resolution of the hostname — it may resolve to a private IP unexpectedly"],"exampleFix":"// before\nbaseURL := \"http://127.0.0.1:8080\"\n// after\nbaseURL := \"https://api.example-inference.com\"","handlingStrategy":"validation","validationCode":"u, err := url.Parse(baseURL)\nif err != nil {\n    return err\n}\nips, err := net.LookupIP(u.Hostname())\nif err != nil {\n    return err\n}\nfor _, ip := range ips {\n    if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() {\n        return fmt.Errorf(\"%s resolves to internal IP %s — will be blocked by SSRF guard\", u.Host, ip)\n    }\n}","typeGuard":null,"tryCatchPattern":"_, err := client.Do(req)\nif err != nil && strings.Contains(err.Error(), \"refusing to dial internal address\") {\n    return fmt.Errorf(\"endpoint blocked by SSRF protection; use a public endpoint: %w\", err)\n}","preventionTips":["Use public, routable endpoints for module integrations","Check DNS resolution of hostnames before configuring them","Remember localhost/private IPs are intentionally blocked — don't point modules at in-cluster services","If self-hosting inference, expose it on an address your SSRF policy allows"],"tags":["ssrf","security","network","private-ip"],"backgroundTag":"ssrf-blocked-internal-address","analyzedSha":"75aa4b6d11f8818305aafd4440b4e32794f7ca04","analyzedAt":"2026-09-04T14:58:20.392Z","contentChangedAt":"2026-09-04T14:58:20.392Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}