{"record":{"id":"81dafa98a82ff3a9","repo":"larksuite/cli","slug":"redirect-from-https-to-http-is-not-allowed","errorCode":null,"errorMessage":"redirect from https to http is not allowed","messagePattern":"redirect from https to http is not allowed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/validate/url.go","lineNumber":149,"sourceCode":"\t\tbase = &http.Client{}\n\t}\n\tif opts.MaxRedirects <= 0 {\n\t\topts.MaxRedirects = defaultDownloadMaxRedirects\n\t}\n\n\tcloned := *base\n\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}","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/validate/url.go#L131-L167","documentation":"The CheckRedirect policy in NewDownloadHTTPClient rejects any redirect that downgrades from https to http. This is a deliberate security control (internal/validate/url.go:149): a TLS-protected source must not silently redirect to plaintext, which would allow interception or tampering of the download. The redirect is aborted and the error is returned from the http.Client call.","triggerScenarios":"A download started from an https:// URL whose server responds with a 3xx pointing at an http:// URL, on a client built by NewDownloadHTTPClient.","commonSituations":"Legacy servers that redirect https to http mirrors; misconfigured hosting that serves http Location headers; testing against a local http server redirected from an https entry point.","solutions":["Use an https:// target URL that does not redirect to http; ask the source owner to fix the redirect.","If plaintext is genuinely acceptable (e.g. tests), set AllowHTTP: true — note this only permits http generally, the https->http downgrade is still blocked, so you must start from an http URL instead.","Fetch the final http URL directly with an explicitly http (AllowHTTP) client rather than following the downgrade redirect."],"exampleFix":"// before: starts at https but server redirects to http mirror\nresp, err := client.Get(\"https://example.com/file.bin\")\n// after: go straight to the plaintext mirror only if allowed\nclient := validate.NewDownloadHTTPClient(base, validate.DownloadHTTPClientOptions{AllowHTTP: true})\nresp, err := client.Get(\"http://mirror.example.com/file.bin\")","handlingStrategy":"validation","validationCode":"u, err := url.Parse(src)\nif err != nil || u.Scheme != \"https\" {\n    return fmt.Errorf(\"download source must be https\")\n}\n// Probe the URL's redirect chain and reject any http Location.","typeGuard":null,"tryCatchPattern":"resp, err := client.Get(url)\nif err != nil {\n    if strings.Contains(err.Error(), \"https to http\") {\n        return fmt.Errorf(\"source downgrades TLS; use a different mirror: %w\", err)\n    }\n    return err\n}","preventionTips":["Only configure https:// download sources.","Verify the endpoint's redirect chain with curl -I during configuration.","Never enable AllowHTTP as a workaround for a TLS downgrade; fix the source instead."],"tags":["network","http","tls","redirect","security"],"backgroundTag":"https-to-http-downgrade","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"}