{"record":{"id":"dfb67ab5eaf5e915","repo":"larksuite/cli","slug":"download-request-url-is-missing","errorCode":null,"errorMessage":"download request URL is missing","messagePattern":"download request URL is missing","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/validate/url.go","lineNumber":386,"sourceCode":"\t\tproxied:            proxied,\n\t\tlookupIP:           lookupIP,\n\t\tproxiedByTLSServer: make(map[string]*http.Transport),\n\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","sourceCodeStart":368,"sourceCodeEnd":404,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/validate/url.go#L368-L404","documentation":"pinDownloadRequestTargetToIP rewrites the outgoing download request so its host is the already-validated target IP. It throws this error when the request or its URL is nil, because there is no target to pin or validate. This is a defensive guard against a malformed request reaching the SSRF-pinning step.","triggerScenarios":"RoundTrip passes a nil *http.Request, or a request constructed without a URL (e.g. http.NewRequest failed and its error was ignored, leaving a zero-value request).","commonSituations":"Ignoring the error from http.NewRequest and using the nil request; custom transport chains that strip or rebuild requests; tests feeding hand-built request structs directly into RoundTrip.","solutions":["Check the error from http.NewRequest before using the request","Ensure only fully-formed requests enter the download transport's RoundTrip","If building requests manually, always set req.URL","Audit middleware/transport wrappers that may drop the URL field"],"exampleFix":"// before\nreq, _ := http.NewRequestWithContext(ctx, \"GET\", rawURL, nil)\nresp, err := client.Do(req)\n// after\nreq, err := http.NewRequestWithContext(ctx, \"GET\", rawURL, nil)\nif err != nil {\n    return err\n}\nresp, err := client.Do(req)","handlingStrategy":"validation","validationCode":"func validRequest(req *http.Request) bool {\n    return req != nil && req.URL != nil && req.URL.Scheme != \"\"\n}\nif !validRequest(req) { return fmt.Errorf(\"request and URL must be set before download\") }","typeGuard":"if req == nil || req.URL == nil { return nil, errors.New(\"download request URL is missing\") }","tryCatchPattern":"if _, err := client.Do(req); err != nil && strings.Contains(err.Error(), \"download request URL is missing\") {\n    return fmt.Errorf(\"malformed request reached download transport: %w\", err)\n}","preventionTips":["Always check the error return of http.NewRequest before using the request","Never pass zero-value http.Request structs into RoundTrip","Add a preflight URL check in callers that build requests dynamically","Keep transport wrappers non-destructive to req.URL"],"tags":["http","ssrf","request","validation"],"backgroundTag":"nil-request-url","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"}