GitHub Advisoryadvisory · Go
GHSA-x677-9fxg-v5c5 Traefik: Incomplete fix for CVE-2026-33433 + CVE-2026-39858 cross-cohort: headerField underscore-variant identity spoofing in BasicAuth / DigestAuth / ForwardAuth
HIGH
Official page ↗
- Aliases
- CVE-2026-54763
- Ecosystem
- Go
- Packages
- github.com/traefik/traefik/v2, github.com/traefik/traefik/v3
- Severity
- High
- CVSS vector
- CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:H/SA:N
- Weaknesses
- CWE-178, CWE-290, CWE-345
- Reviewed
- 2026-08-06
Affected packages
• Go github.com/traefik/traefik/v2: < 2.11.51 → fixed in 2.11.51
• Go github.com/traefik/traefik/v3: < 3.6.22 → fixed in 3.6.22
• Go github.com/traefik/traefik/v3: >= 3.7.0, < 3.7.6 → fixed in 3.7.6
Description
Summary
There is a high severity vulnerability in Traefik's BasicAuth, DigestAuth, and ForwardAuth
middlewares. The fix for CVE-2026-33433 stripped canonical-cased spoofed identity headers
(e.g. `X-Auth-User`) before writing Traefik's own value, but did not account for
underscore-variant header names (e.g. `X_Auth_User`), which many backends normalize
identically to the dashed form. An attacker able to reach a protected route could inject
an underscore-variant header that survives Traefik's stripping and reaches the backend
alongside — or, on the unauthenticated ForwardAuth `authResponseHeaders` path, instead of
— the value Traefik intended to set, spoofing identity or authorization context. This is
fixed by setting the new `allowHeadersWithUnderscores: false` entry point option, which
strips all headers with underscores in their names before routing.
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.
Original Description
Incomplete fix for CVE-2026-33433 + CVE-2026-39858 cross-cohort: `headerField` underscore-variant identity spoofing in BasicAuth / DigestAuth / ForwardAuth
Summary
The fix for CVE-2026-33433 (GHSA-qr99-7898-vr7c, "BasicAuth/DigestAuth Identity Spoofing via Non-Canonical headerField", patched in v2.11.42 / v3.6.12 / v3.7.0-ea.3) added `req.Header.Del(headerField)` before the literal-key writeback in `pkg/middlewares/auth/basic_auth.go` and `pkg/middlewares/auth/digest_auth.go`. Go's `Header.Del` calls `textproto.CanonicalMIMEHeaderKey` which canonicalizes ASCII CASE and treats `-` as a word separator — so the fix correctly strips canonical-cased attacker headers (`X-Auth-User`, `x-auth-user`, `X-AUTH-USER`, etc.).
However, `textproto.CanonicalMIMEHeaderKey` does NOT treat `_` as a separator. Attacker-supplied underscore-variant headers such as `X_Auth_User` survive `Header.Del("X-Auth-User")` intact and are forwarded to the backend alongside Traefik's own writeback. Many common backends (CGI/WSGI per RFC 3875, PHP `$_SERVER`, nginx with `underscores_in_headers on`, Tomcat / Java EE servlet containers, ASGI/WSGI frameworks) normalize `_` ↔ `-` equivalently or expose both forms to application code that may read the attacker's value.
This is the direct cross-cohort sibling of the threat model the maintainer accepted in CVE-2026-39858 (GHSA-5m6w-wvh7-57vm, "Forwarded alias spoofing pre-auth decision bypass"), which fixed the underscore-variant of the X-Forwarded-* family via `isManagedXHeader` in `pkg/middlewares/forwardedheaders/forwarded_header.go`. The CVE-2026-39858 advisory body states verbatim:
> "When the backend normalizes underscore and dash header forms equivalently, an attacker can inject spoofed trust context — such as a trusted scheme or host — through the alias headers and bypass authentication on protected routes without valid credentials."
The same threat model applies to the operator-configurable `headerField` (BasicAuth, DigestAuth) and `authResponseHeaders` (ForwardAuth, ingress-nginx snippet provider), but the underscore-handling primitive (`isManagedXHeader`) was not extended to those middlewares. I verified the bypass end-to-end on `traefik:v3.6.14` (the latest patched release containing both fixes) using a default-recommended canonical `headerField: "X-Auth-User"` config and reproduced the bypass with a single `curl -H "X_Auth_User: superadmin" ...` request alongside valid BasicAuth credentials.
The defect is present in four code paths at HEAD `eec68dce064f843b4317c4393aaea81b6dea31d6`:
1. `pkg/middlewares/auth/basic_auth.go:101-105` — BasicAuth `headerField`
2. `pkg/middlewares/auth/digest_auth.go:99-103` — DigestAuth `headerField`
3. `pkg/middlewares/auth/forward.go:304-310` — ForwardAuth `authResponseHeaders` per-name writeback
4. `pkg/middlewares/ingressnginx/snippet/snippet.go:480-486` — Ingress-NGINX snippet `authResponseHeaders` per-name writeback
The ForwardAuth instance (#3) is particularly notable: the attacker does NOT need credentials. The `authResponseHeaders` mechanism is intended to copy identity headers from the trusted auth server only; the underscore-variant bypass lets an unauthenticated attacker pre-inject the same identity header before any auth happens.
The fast proxy at `pkg/proxy/fast/proxy.go:139` explicitly calls `DisableNormalizing()` on the outgoing fasthttp request, guaranteeing that the underscore-variant header reaches the backend wire verbatim. The standard `httputil.ReverseProxy` path at `pkg/proxy/httputil/proxy.go:55` likewise copies `req.Header` keys as-is during the wire write.
Affected versions
• `traefik` v3.6.x ≤ 3.6.14, v3.7.x ≤ 3.7.0-rc.2, v2.11.x ≤ 2.11.43, and all earlier versions sharing the same auth middleware architecture.
The defect is present at HEAD post-CVE-2026-33433 fix (the fix added the `Del` line but the literal-key write defect-class survives for underscore variants).
Root cause
In `pkg/middlewares/auth/basic_auth.go` at HEAD `eec68dc`:
```go
if b.headerField != "" {
// TODO Deprecated we should add the header with canonical key.
req.Header.Del(b.headerField)
req.Header[b.headerField] = []string{user}
}
```
The TODO comment shows the maintainer is aware of the literal-key write problem in general (canonical-key write would solve the case-canonicalization issue more cleanly than the current `Del` + literal-write pair). The comment does not acknowledge the underscore-variant survival corollary.
`pkg/middlewares/auth/digest_auth.go:99-103` and the two ForwardAuth paths follow the same `Del` + literal-write pattern. Each is independently exploitable; the underlying primitive defect is shared.
The maintainer's gold-standard primitive for handling this exact threat class is `pkg/middlewares/forwardedheaders/forwarded_header.go:53-66`:
```go
func isManagedXHeader(key string) bool {
if len(key) == 0 || key[0] != 'X' { return false }
if _, ok := XHeadersSet[key]; ok { return true }
if strings.IndexByte(key, '_') /traefik-ht1a-poc; commands below are verbatim.
Setup
```yaml
docker-compose.yml
services:
traefik:
image: traefik:v3.6.14
command:
• --providers.file.filename=/etc/traefik/dynamic.yml
• --entrypoints.web.address=:80
ports:
• "8080:80"
volumes:
• ./traefik/dynamic.yml:/etc/traefik/dynamic.yml:ro
echo:
image: mendhak/http-https-echo:36
environment:
• HTTP_PORT=8888
```
```yaml
traefik/dynamic.yml — canonical headerField, recommended operator config
http:
routers:
protected:
rule: "PathPrefix(`/`)"
service: echo
middlewares: [basic-auth]
services:
echo:
loadBalancer:
servers: [{url: "http://echo:8888"}]
middlewares:
basic-auth:
basicAuth:
users:
• 'alice:$2b$05$FhDfYidZdDPuQjovYqcTAe22wHpQ/cILC7Tr2yAD6vLlvZh/Q45PC' # alice:secret123
headerField: "X-Auth-User"
```
`docker compose up -d`.
Test 1 (control — CVE-2026-33433 fix works for canonical case)
```bash
$ curl -s -u alice:secret123 -H "X-Auth-User: superadmin" http://localhost:8080/
{
...
…
Related
Alias · CVE (1)
- CVE-2026-54763 Traefik is an HTTP reverse proxy and load balancer. vulnerability
References
- https://github.com/traefik/traefik/security/advisories/GHSA-x677-9fxg-v5c5 web
- https://nvd.nist.gov/vuln/detail/CVE-2026-54763 advisory
- https://github.com/traefik/traefik/pull/13262 web
- https://github.com/traefik/traefik/commit/108a5264473a2cbc8f12d6d691a3c6553cdf2c1b web
- https://github.com/traefik/traefik package
- https://github.com/traefik/traefik/releases/tag/v2.11.51 web
- https://github.com/traefik/traefik/releases/tag/v3.6.22 web
- https://github.com/traefik/traefik/releases/tag/v3.7.6 web