Know every vulnerabilitybefore it knows you.
DevGuard continuously monitors your dependencies and alerts you when CVEs like this one affect your stack — with real-time threat intelligence built for developers.
GHSA-3q9r-p662-5j8m
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):
// 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:
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>The vulnerability can be exploited over the network without needing physical access. It is easy for an attacker to exploit this vulnerability. An attacker does not need any special privileges or access rights. No user interaction is needed for the attacker to exploit this vulnerability. The vulnerability can affect other systems as well, not just the initial system. There is a low impact on the integrity of the data.
Exploitation attempts have been detected. Elevated vigilance and prompt remediation are advised.
The exploit probability is very low. The vulnerability is unlikely to be exploited in the next 30 days.
We did not find any exploit available. Neither in GitHub repositories nor in the Exploit-Database.
Browse More
Continuously monitor your dependencies and get alerted when vulnerabilities like this one affect your stack.
Checkout DevGuard