{"record":{"id":"1b53852eeff80d22","repo":"larksuite/cli","slug":"blocked-download-target-local-internal-host-is-no","errorCode":null,"errorMessage":"blocked download target: local/internal host is not allowed","messagePattern":"blocked download target: local/internal host is not allowed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/validate/url.go","lineNumber":389,"sourceCode":"\t}, true\n}\n\nfunc cloneDownloadHTTPTransport(source *http.Transport) *http.Transport {\n\tcloned := source.Clone()\n\tif cloned.TLSNextProto == nil {\n\t\tif _, ok := source.TLSNextProto[\"h2\"]; ok {\n\t\t\tcloned.ForceAttemptHTTP2 = true\n\t\t}\n\t}\n\treturn cloned\n}\n\nfunc pinDownloadRequestTargetToIP(req *http.Request, targetIP net.IP) (*http.Request, error) {\n\tif req == nil || req.URL == nil {\n\t\treturn nil, fmt.Errorf(\"download request URL is missing\")\n\t}\n\tif targetIP == nil || isRestrictedDownloadIP(targetIP) {\n\t\treturn nil, fmt.Errorf(\"blocked download target: local/internal host is not allowed\")\n\t}\n\n\toriginalHost := req.URL.Host\n\tpinnedHost := targetIP.String()\n\tif port := req.URL.Port(); port != \"\" {\n\t\tpinnedHost = net.JoinHostPort(pinnedHost, port)\n\t} else if strings.Contains(pinnedHost, \":\") {\n\t\tpinnedHost = \"[\" + pinnedHost + \"]\"\n\t}\n\n\tpinned := req.Clone(req.Context())\n\tpinnedURL := *req.URL\n\tpinnedURL.Host = pinnedHost\n\tpinned.URL = &pinnedURL\n\tpinned.Host = originalHost\n\treturn pinned, nil\n}\n","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/validate/url.go#L371-L407","documentation":"This is the SSRF guard of the download path: pinDownloadRequestTargetToIP rejects the request when the resolved target IP is nil or is a restricted (loopback, link-local, private, etc.) address. The download flow validates the host once, then pins the connection to that validated IP so DNS cannot be re-resolved to an internal address later. Hitting this error means the destination resolved to a local/internal IP, which the CLI refuses to contact.","triggerScenarios":"The URL host resolves to 127.0.0.1/::1, 169.254.x.x, RFC1918 (10/8, 172.16/12, 192.168/16), or another address matched by isRestrictedDownloadIP; or no IP could be determined (targetIP nil).","commonSituations":"Pointing a download at localhost or an internal service by mistake; a DNS name (or attacker-controlled redirect) resolving to an internal IP; IPv6 loopback addresses; misconfigured download URL in config using an internal hostname.","solutions":["Use a public internet URL for the download target","Verify DNS resolution of the hostname with dig/nslookup; if it returns a private IP, the host is not a valid public download endpoint","If this is a legitimate internal download, use the approved internal transfer mechanism instead of the public download path","Check for typos in the scheme/host (e.g. localhost vs the real host)"],"exampleFix":"// before\ndlURL := \"http://127.0.0.1:8080/file.bin\" // blocked\n// after\ndlURL := \"https://open.feishu.cn/file.bin\" // public target passes SSRF guard","handlingStrategy":"validation","validationCode":"// Pre-check the resolved target before calling the download API\nips, err := net.LookupIP(host)\nif err != nil { return err }\nfor _, ip := range ips {\n    if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() {\n        return fmt.Errorf(\"%s resolves to restricted IP %s; use a public URL\", host, ip)\n    }\n}","typeGuard":"func isPublicIP(ip net.IP) bool {\n    return ip != nil && !ip.IsLoopback() && !ip.IsPrivate() && !ip.IsLinkLocalUnicast() && !ip.IsUnspecified()\n}","tryCatchPattern":"if err := download(url); err != nil && strings.Contains(err.Error(), \"local/internal host is not allowed\") {\n    return fmt.Errorf(\"download target %s is internal/blocked by SSRF policy: %w\", url, err)\n}","preventionTips":["Use public HTTPS endpoints for downloads","Resolve the hostname yourself before downloading to catch private IPs early","Watch for redirects to internal hosts; keep redirects enabled only within the validated target","Treat this error as a signal of misconfiguration or a suspicious URL, not a transient failure"],"tags":["ssrf","security","network","download"],"backgroundTag":"ssrf-blocked-internal-host","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}