{"id":"fb95879e623ced97","repo":"gofiber/fiber","slug":"proxy-https-to-http-redirect-blocked","errorCode":null,"errorMessage":"proxy: HTTPS to HTTP redirect blocked","messagePattern":"proxy: HTTPS to HTTP redirect blocked","errorType":"exception","errorClass":"ErrRedirectDowngrade","httpStatus":null,"severity":"warning","filePath":"middleware/proxy/security.go","lineNumber":65,"sourceCode":"var (\n\t// ErrUpstreamSchemeNotAllowed is returned when the proxied URL uses a\n\t// scheme outside the configured allowlist (default: http, https).\n\tErrUpstreamSchemeNotAllowed = errors.New(\"proxy: upstream scheme is not allowed\")\n\n\t// ErrUpstreamHostInvalid is returned when the proxied URL is missing a\n\t// host or cannot be parsed.\n\tErrUpstreamHostInvalid = errors.New(\"proxy: upstream host is empty or invalid\")\n\n\t// ErrUpstreamHostBlocked is returned when the proxied URL resolves to\n\t// an address inside a blocked range (loopback, RFC 1918 private,\n\t// link-local, multicast, unspecified, or CGNAT) and AllowPrivateIPs\n\t// is false.\n\tErrUpstreamHostBlocked = errors.New(\"proxy: upstream host resolves to a blocked address\")\n\n\t// ErrRedirectDowngrade is returned when DoRedirects encounters a\n\t// redirect from an HTTPS upstream to a plaintext HTTP target and\n\t// AllowHTTPSDowngrade is false.\n\tErrRedirectDowngrade = errors.New(\"proxy: HTTPS to HTTP redirect blocked\")\n)\n\n// SecurityPolicy controls runtime security restrictions applied to the\n// proxy.Do, proxy.Forward, proxy.DoRedirects, proxy.DoTimeout, and\n// proxy.DoDeadline runtime helpers as well as Balancer instances that\n// do not supply their own policy via Config.SecurityPolicy.\ntype SecurityPolicy struct {\n\t// AllowedSchemes restricts the URL schemes accepted as upstream\n\t// targets. Empty defaults to []string{schemeHTTP, schemeHTTPS}.\n\tAllowedSchemes []string\n\n\t// AllowPrivateIPs allows upstream hosts to resolve to loopback,\n\t// private (RFC 1918), link-local, multicast, unspecified, or CGNAT\n\t// (RFC 6598) addresses. SECURITY: enabling this exposes the proxy\n\t// to SSRF attacks against internal services such as cloud\n\t// metadata endpoints. Default: false.\n\t//\n\t// DNS-rebinding scope: when false, the resolved IP is re-validated at","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/middleware/proxy/security.go#L47-L83","documentation":"Returned as ErrRedirectDowngrade by proxy.DoRedirects when an HTTPS upstream responds with a 3xx redirect whose Location points to a plaintext http:// URL and SecurityPolicy.AllowHTTPSDowngrade is false. The guard prevents silent protocol downgrades that would expose credentials, cookies, or Authorization headers over an unencrypted hop. AllowHTTPSDowngrade defaults to false for security.","triggerScenarios":"proxy.DoRedirects(req, 'https://api.example.com/...') where api.example.com returns 302 Location: http://api.example.com/... (scheme mismatch). Common with misconfigured upstreams that canonicalize to http, or HSTS-less backends behind a TLS-terminating load balancer that advertise http in redirects.","commonSituations":"Upstream behind a TLS terminator that emits http:// in its redirect Location; mixing schemes across a proxy chain; enabling DoRedirects to follow a login/oauth redirect that crosses schemes; stricter default after a Fiber security-policy upgrade.","solutions":["Fix the upstream to emit https:// in its redirect Location (correct long-term fix).","If you accept the plaintext risk for this hop, set SecurityPolicy{AllowHTTPSDowngrade: true} on the proxy Config/policy — credentials may leak on the downgraded hop.","Use proxy.Do (no redirect-following) instead of proxy.DoRedirects to avoid following cross-scheme redirects entirely.","Verify the upstream enforces HSTS / TLS on all hops so no http Location is generated."],"exampleFix":"// before\nproxy.DoRedirects(req, 'https://upstream/path')\n\n// after — accept downgrade risk explicitly\npolicy := proxy.DefaultSecurityPolicy()\npolicy.AllowHTTPSDowngrade = true\nproxy.WithSecurityPolicy(policy)\nproxy.DoRedirects(req, 'https://upstream/path')","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := proxy.DoRedirects(req, target); err != nil {\n    if errors.Is(err, proxy.ErrRedirectDowngrade) {\n        // upstream tried to redirect from https to http\n        return fiber.NewError(fiber.StatusBadGateway, \"insecure redirect from upstream\")\n    }\n    return err\n}","preventionTips":["Prefer proxy.Do (no redirect-following) when you don't need cross-scheme redirects.","Ensure upstreams emit https:// in Location headers (correct HSTS / TLS config).","Only enable AllowHTTPSDowngrade on a trusted hop where credential leakage is acceptable."],"tags":["proxy","redirect","security","tls","https"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}