{"record":{"id":"0da1198ff3ec48cc","repo":"larksuite/cli","slug":"blocked-redirect-target-w","errorCode":null,"errorMessage":"blocked redirect target: %w","messagePattern":"blocked redirect target: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/validate/url.go","lineNumber":156,"sourceCode":"\tcloned.Transport = &downloadSchemeTransport{\n\t\tbase:      cloneDownloadTransport(base.Transport),\n\t\tallowHTTP: opts.AllowHTTP,\n\t}\n\tcloned.CheckRedirect = func(req *http.Request, via []*http.Request) error {\n\t\tif len(via) >= opts.MaxRedirects {\n\t\t\treturn fmt.Errorf(\"too many redirects\")\n\t\t}\n\t\tif len(via) > 0 {\n\t\t\tprev := via[len(via)-1]\n\t\t\tif strings.EqualFold(prev.URL.Scheme, \"https\") && strings.EqualFold(req.URL.Scheme, \"http\") {\n\t\t\t\treturn fmt.Errorf(\"redirect from https to http is not allowed\")\n\t\t\t}\n\t\t}\n\t\tif !opts.AllowHTTP && !strings.EqualFold(req.URL.Scheme, \"https\") {\n\t\t\treturn fmt.Errorf(\"only https URLs are supported\")\n\t\t}\n\t\tif err := ValidateDownloadSourceURL(req.Context(), req.URL.String()); err != nil {\n\t\t\treturn fmt.Errorf(\"blocked redirect target: %w\", err)\n\t\t}\n\t\treturn nil\n\t}\n\n\treturn &cloned\n}\n\ntype downloadSchemeTransport struct {\n\tbase      http.RoundTripper\n\tallowHTTP bool\n}\n\nfunc (t *downloadSchemeTransport) RoundTrip(req *http.Request) (*http.Response, error) {\n\tif req == nil || req.URL == nil {\n\t\treturn nil, errs.NewInternalError(\n\t\t\terrs.SubtypeUnknown,\n\t\t\t\"download transport received a nil request\",\n\t\t)","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/validate/url.go#L138-L174","documentation":"On every redirect, CheckRedirect re-runs ValidateDownloadSourceURL on the redirect target (internal/validate/url.go:156). That validator rejects malformed URLs, non-http/https schemes, and hosts that resolve to localhost or private/restricted IP ranges (SSRF protection). When it fails, the redirect is wrapped as 'blocked redirect target' and the request aborts — the library refuses to be redirected into an internal network.","triggerScenarios":"A redirect whose Location points to localhost, 127.0.0.1, RFC1918/private ranges, link-local/CGNAT/multicast addresses, an unresolvable hostname ('failed to resolve host'), or a non-http/https scheme — while following redirects on a NewDownloadHTTPClient client.","commonSituations":"A compromised or misbehaving source redirecting into cloud metadata endpoints (169.254.169.254); internal staging hosts that 302 to intranet URLs; DNS failures in constrained environments; redirect to an unusual scheme like file://.","solutions":["Inspect the redirect target (final URL in the error context) and use a URL on a public host that does not redirect into private ranges.","Verify DNS resolution of the redirect host from the runtime environment; fix resolver/connectivity issues if 'failed to resolve host' is the cause.","Do not attempt to bypass: the private/localhost blocklist is deliberate SSRF protection; move the asset to a public HTTPS location instead."],"exampleFix":"// before: endpoint redirects to internal host\nresp, err := client.Get(\"https://files.example.com/dl\") // 302 -> http://10.0.0.5/asset\n// after: serve a direct public URL\nresp, err := client.Get(\"https://cdn.example.com/asset\")","handlingStrategy":"validation","validationCode":"// Pre-screen the URL with the library's own validator before downloading.\nif err := validate.ValidateDownloadSourceURL(ctx, src); err != nil {\n    return fmt.Errorf(\"download source rejected upfront: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"resp, err := client.Get(url)\nif err != nil {\n    var blocked bool\n    if strings.Contains(err.Error(), \"blocked redirect target\") {\n        blocked = true\n    }\n    if blocked {\n        return fmt.Errorf(\"source redirects into a restricted network; refusing: %w\", err)\n    }\n    return err\n}","preventionTips":["Run ValidateDownloadSourceURL on source URLs before download attempts for fail-fast behavior.","Only download from vetted public hosts; never from user-supplied URLs without validation.","Ensure the runtime has working DNS so legitimate hosts do not fail resolution mid-redirect."],"tags":["network","security","ssrf","redirect","dns"],"backgroundTag":"ssrf-redirect-blocked","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"}