Skip to content

GHSA-3q9r-p662-5j8m CVE-2026-54764 GO-2026-6202

Traefik: ForwardAuth middleware leaks X-Forwarded-Port spoofing via untrusted X-Forwarded-Proto when trustForwardHeader=false

Medium Go
Severity
0.0 / 10
Medium · CVSS 4.0
Exploit chance (EPSS)
0.28%
Chance of exploitation in the next 30 days. Higher than 20.61% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-345 Insufficient Verification of Data Authenticity
Fix
Available
2 packages have a fixed version

Description

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

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>


Affected versions

Go

PackageVulnerableFixed in
github.com/traefik/traefik
<= 1.7.34
No fix yet
github.com/traefik/traefik
all versions
No fix yet
github.com/traefik/traefik/v2
< 2.11.51
2.11.51
github.com/traefik/traefik/v3
< 3.6.22
3.6.22
github.com/traefik/traefik/v3
>= 3.7.0, < 3.7.6
3.7.6
github.com/traefik/traefik/v3
< 3.6.22
>= 3.7.0, < 3.7.6
3.6.22
3.7.6

How to fix

Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.

github.com/traefik/traefik/v2 Go → 2.11.51

go
go get github.com/traefik/traefik/v2@v2.11.51 && go mod tidy

github.com/traefik/traefik/v3 Go → 3.6.22

go
go get github.com/traefik/traefik/v3@v3.6.22 && go mod tidy

Severity breakdown

CVSS 4.0 0.0

CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:N/SI:L/SA:N

Attack vector
Network
Attack complexity
Low
Attack requirements
None
Privileges required
None
User interaction
None
Confidentiality (vulnerable system)
None
Integrity (vulnerable system)
None
Availability (vulnerable system)
None
Confidentiality (subsequent systems)
None
Integrity (subsequent systems)
Low
Availability (subsequent systems)
None

CVSS 3.1 5.8

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:L/A:N

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Changed
Confidentiality
None
Integrity
Low
Availability
None

Weakness

CWE-345: Insufficient Verification of Data Authenticity

The product does not sufficiently verify the origin or authenticity of data, in a way that causes it to accept invalid data.

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
GO-2026-6558
Traefik: BasicAuth singleflight coalescing reintroduces an unauthenticated username-enumeration timing oracle
Medium Also affects github.com/traefik/traefik
GHSA-f52w-8j3h-j724
Traefik: Rootless HTTP/1 request-target routes as "/" but is forwarded verbatim, bypassing path-scoped routing, middleware guards and access logging
High Also affects github.com/traefik/traefik
GHSA-w4v4-9rw7-5326
Traefik: Inconsistent Interpretation of HTTP Requests ('HTTP Request/Response Smuggling') and Incorrect Authorization
Critical Also affects github.com/traefik/traefik
GHSA-qqjf-53cj-pwvv
Traefik HTTP/3 Backend NTLM Connection Reuse
Critical Also affects github.com/traefik/traefik
GO-2026-6467
Traefik entrypoint header-name sanitization bypassed via request trailers
High Also affects github.com/traefik/traefik
GHSA-rf44-j88r-hh8c
Traefik: ForwardAuth identity spoofing via dot-form header alias
High Also affects github.com/traefik/traefik
GHSA-7ghq-v6jf-g56c
Traefik: respondingTimeouts.readTimeout is not applied to HTTP/3, leaving slow-body uploads unbounded
Medium Also affects github.com/traefik/traefik
GHSA-62fc-8686-hfmq
Traefik: `allowCrossNamespace=false` bypass via `@kubernetescrd` TraefikService backendRef
Medium Also affects github.com/traefik/traefik
Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor