gofiber/fiber · error
ErrRedirectDowngrade
ErrRedirectDowngrade
Error message
proxy: HTTPS to HTTP redirect blocked
What it means
When following upstream redirects (DoRedirects), the proxy refuses to follow an HTTPS-to-HTTP redirect unless AllowHTTPSDowngrade is true. This prevents TLS stripping: a compromised or misconfigured upstream could otherwise redirect the proxy to plaintext, exposing tokens/bodies. The check compares the new Location's scheme against httpsSchemeBytes.
Source
Thrown at middleware/proxy/security.go:66
var (
// ErrUpstreamSchemeNotAllowed is returned when the proxied URL uses a
// scheme outside the configured allowlist (default: http, https).
ErrUpstreamSchemeNotAllowed = errors.New("proxy: upstream scheme is not allowed")
// ErrUpstreamHostInvalid is returned when the proxied URL is missing a
// host or cannot be parsed.
ErrUpstreamHostInvalid = errors.New("proxy: upstream host is empty or invalid")
// ErrUpstreamHostBlocked is returned when the proxied URL resolves to
// an address inside a blocked range (loopback, RFC 1918 private,
// link-local, multicast, unspecified, or CGNAT) and AllowPrivateIPs
// is false.
ErrUpstreamHostBlocked = errors.New("proxy: upstream host resolves to a blocked address")
// ErrRedirectDowngrade is returned when DoRedirects encounters a
// redirect from an HTTPS upstream to a plaintext HTTP target and
// AllowHTTPSDowngrade is false.
ErrRedirectDowngrade = errors.New("proxy: HTTPS to HTTP redirect blocked")
)
// SecurityPolicy controls runtime security restrictions applied to the
// proxy.Do, proxy.Forward, proxy.DoRedirects, proxy.DoTimeout, and
// proxy.DoDeadline runtime helpers as well as Balancer instances that
// do not supply their own policy via Config.SecurityPolicy.
type SecurityPolicy struct {
// AllowedSchemes restricts the URL schemes accepted as upstream
// targets. Empty defaults to []string{schemeHTTP, schemeHTTPS}.
AllowedSchemes []string
// AllowPrivateIPs allows upstream hosts to resolve to loopback,
// private (RFC 1918), link-local, multicast, unspecified, or CGNAT
// (RFC 6598) addresses. SECURITY: enabling this exposes the proxy
// to SSRF attacks against internal services such as cloud
// metadata endpoints. Default: false.
//
// DNS-rebinding scope: when false, the resolved IP is re-validated atView on GitHub (pinned to a105acad6c)
Solutions
- Fix the upstream to redirect to an https:// Location.
- If the downgrade is acceptable in your environment, set SecurityPolicy.AllowHTTPSDowngrade=true and record the security trade-off.
- Disable redirect following (use proxy.Do instead of proxy.DoRedirects) and handle redirects explicitly.
- Pin allowed redirect targets so an open redirect can't force a downgrade.
Example fix
// before
cfg := proxy.Config{ /* AllowHTTPSDowngrade defaults to false */ }
return proxy.DoRedirects(c, url, cfg)
// after (only if downgrade is acceptable)
cfg := proxy.Config{
SecurityPolicy: &proxy.SecurityPolicy{AllowHTTPSDowngrade: true},
}
return proxy.DoRedirects(c, url, cfg) Defensive patterns
Strategy: validation
Validate before calling
if u.Scheme == "https" && policy.AllowHTTPSDowngrade == false {
// after each redirect, re-check the new Location's scheme
if loc, err := res.Location(); err == nil && loc.Scheme == "http" {
return fiber.NewError(fiber.StatusBadGateway, "refusing TLS downgrade")
}
} Type guard
func isDowngrade(from, to *url.URL) bool { return from.Scheme == "https" && to.Scheme == "http" } Prevention
- Pin allowed redirect hosts so an open redirect can't force a downgrade.
- Prefer DoRedirects with a SecurityPolicy over manual redirect loops.
- Default-deny downgrades unless your environment explicitly tolerates them.
When it happens
Trigger: An HTTPS upstream returns 301/302/303/307/308 with a Location header whose URL is http://, while SecurityPolicy.AllowHTTPSDowngrade is false (default).
Common situations: Misconfigured upstream that redirects to its plaintext port; captive portals; mixed-environment deploys where staging is http but prod is https; load balancers stripping TLS in front of the upstream.
Related errors
- client: HTTPS to HTTP redirect blocked
- proxy: upstream scheme is not allowed
- ErrUpstreamHostBlocked
- %w: %w
- tls: cannot load TLS key pair from certFile=%q and keyFile=%
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/ba5b328ec97afbff.
Report an issue: GitHub.