GHSA-3q9r-p662-5j8m: Medium severity go/github.com/traefik/traefik vulnerability
Summary
There is a medium severity vulnerability in Traefik's ForwardAuth middleware. Even when configured with trustForwardHeader: false, Traefik derives the X-Forwarded-Port header sent to the authentication service from the original incoming request instead of the sanitized forwarded request. As a result, an unauthenticated remote attacker can inject an X-Forwarded-Proto: https header over a plain HTTP connection and cause Traefik to forward X-Forwarded-Port: 443 to the auth service, bypassing port-based authorization checks. This is a regression of the incomplete fix for GHSA-6384-m2mw-rf54, which addressed the X-Forwarded-Proto and X-Forwarded-Prefix spoofing vectors but missed the X-Forwarded-Port vector.
Patches
- https://github.com/traefik/traefik/releases/tag/v2.11.51 - https://github.com/traefik/traefik/releases/tag/v3.6.22 - https://github.com/traefik/traefik/releases/tag/v3.7.6
For more information
If you have any questions or comments about this advisory, please open an issue.
<details> <summary>Original Description</summary>
Summary
The ForwardAuth middleware, even when configured with trustForwardHeader: false, still derives the X-Forwarded-Port header sent to the authentication service by reading the attacker-controlled X-Forwarded-Proto header from the original incoming request. This allows an unauthenticated remote attacker to cause Traefik to forward X-Forwarded-Port: 443 to the auth service on a plain HTTP connection, creating an inconsistency that can bypass port-based authorization checks.
### Details
The fix introduced in commit 5e1de2258 (released as part of the April 2026 security advisory GHSA-6384-m2mw-rf54) correctly strips all X-Forwarded- headers from the forwarded auth request when trustForwardHeader=false, and reconstructs X-Forwarded-Proto from the actual TLS state of the connection (req.TLS).
However, the reconstruction of X-Forwarded-Port is delegated to the helper forwardedPort(req) which receives the original request (req) rather than the sanitized forward request (forwardReq):
go // pkg/middlewares/auth/forward.go – writeHeader() if !trustForwardHeader { forwardedheaders.DeleteXForwardedHeaders(forwardReq.Header) // strips all X-Fwd- from forwardReq } // ... if , ok := forwardReq.Header[forwardedheaders.XForwardedPort]; !ok { forwardReq.Header.Set(forwardedheaders.XForwardedPort, forwardedPort(req)) // ← req = ORIGINAL }
// pkg/middlewares/auth/forward.go – forwardedPort() func forwardedPort(req http.Request) string { if , port, err := net.SplitHostPort(req.Host); err == nil && port != "" { return port } // Reads attacker-controlled header on the ORIGINAL request: if req.Header.Get(forwardedheaders.XForwardedProto) == "https" || ... { return "443" } if req.TLS != nil { return "443" } return "80" }
Result when trustForwardHeader=false and attacker sends X-Forwarded-Proto: https on a plain HTTP connection:
┌──────────────────────────────────┬──────────┬────────┐ │ Header forwarded to auth service │ Expected │ Actual │ ├──────────────────────────────────┼──────────┼────────┤ │ X-Forwarded-Proto │ http │ http ✓ │ ├──────────────────────────────────┼──────────┼────────┤ │ X-Forwarded-Port │ 80 │ 443 ✗ │ └──────────────────────────────────┴──────────┴────────┘ The inconsistency between Proto=http and Port=443 is exploitable against any authentication service that gates access based on X-Forwarded-Port.
### PoC
Traefik configuration:
http: middlewares: my-auth: forwardAuth: address: "http://auth-service/" trustForwardHeader: false # security setting, but still bypassable routers: api: rule: "PathPrefix(/api)" middlewares: - my-auth service: backend
Auth service logic (example victim): # auth-service checks: only port 443 requests are considered "secure" port = request.headers.get("X-Forwarded-Port", "80") proto = request.headers.get("X-Forwarded-Proto", "http") if port == "443": return 200 # grant access return 403 Attack:
Plain HTTP connection, no TLS – but spoofs port 443 curl -H "X-Forwarded-Proto: https" http://traefik.example.com/api/admin Auth service receives X-Forwarded-Port: 443 → grants access
Verification: Enable Traefik debug logging and observe X-Forwarded-Port: 443 in the auth request while the connection is plain HTTP.
### Impact
Any deployment using the ForwardAuth middleware with trustForwardHeader: false where the downstream authentication service uses X-Forwarded-Port to make authorization decisions is vulnerable to privilege escalation. An unauthenticated attacker can bypass port-based security checks (e.g., "only allow requests arriving on HTTPS port 443") by injecting a single X-Forwarded-Proto: https header on a plain HTTP connection.
This is a regression of the incomplete fix for GHSA-6384-m2mw-rf54: while the X-Forwarded-Prefix and X-Forwarded-Proto spoofing vectors were addressed, the X-Forwarded-Port vector was missed.
</details>
---
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
go/github.com/traefik/traefik/v3to a version that resolves this vulnerability.Fixed in 3.7.6 - Upgrade
Upgrade
go/github.com/traefik/traefik/v3to a version that resolves this vulnerability.Fixed in 3.6.22 - Upgrade
Upgrade
go/github.com/traefik/traefik/v2to a version that resolves this vulnerability.Fixed in 2.11.51 - Upgrade
Upgrade
traefik/traefikto a version that resolves this vulnerability.Fixed in 2.11.51 - Upgrade
Upgrade
traefik/traefikto a version that resolves this vulnerability.Fixed in 3.6.22 - Upgrade
Upgrade
traefik/traefikto a version that resolves this vulnerability.Fixed in 3.7.6 - Configuration
If using ForwardAuth, ensure trustForwardHeader is set to false (the bypass occurs when trustForwardHeader is false but a request over plain HTTP can spoof X-Forwarded-Port via the original request-derived reconstruction).
Traefik ForwardAuth middleware trustForwardHeader = false - Compensating control
Use a compensating control so that the auth service cannot be tricked by X-Forwarded-Port (e.g., have the auth service base port-based authorization on the actual TLS state of the connection rather than trusting X-Forwarded-Port forwarded by Traefik).
- Operational
After upgrading Traefik to one of the fixed releases, verify by enabling Traefik debug logging and confirming the auth request no longer receives an unexpected header value such as X-Forwarded-Port: 443 when the incoming connection is plain HTTP.