~/f4n6 $ grep -r "Traefik entrypoint header-name sanitization bypassed via request trailers" ./investigations/ --include="*.md"

Traefik entrypoint header-name sanitization bypassed via request trailers

Jeff Davies 11 Sep 2026 12 min read

1. Executive summary

Traefik v3.2.0 through v3.7.12 fails to apply its entrypoint header-name sanitization — aliasHeadersStrategy / underscoreHeadersStrategy in delete or reject mode, and the default stripping of client-supplied X-Forwarded-* — to HTTP request trailers, allowing an unauthenticated client to smuggle sanitized header names (e.g. X_Auth_User, X-Forwarded-Prefix) past the proxy as HTTP/1.1 chunked trailers or HTTP/2 trailers. On chains that include a body-buffering middleware (retry with status codes, or buffering), the trailer carries an attacker-chosen value end-to-end; the reporter demonstrated a 403 → 200 admin authorization flip against a real trailer-merging backend (pre-fix libevent, CVE-2026-63379). The underlying flaw is tracked as CVE-2026-54763 (CVSS 7.8 HIGH, not in CISA KEV, EPSS 0%), with the downstream trailer-merge class tracked as CVE-2026-63379 (CVSS 6.3 MEDIUM, not in CISA KEV, EPSS 1%). Traefik v2 is not affected; the fix is v3.7.13, and end-of-life v3.2–v3.6 lines will not be patched on their own line. For EMEA financial services running Traefik v3 in front of backends that trust proxy-set identity headers or X-Forwarded-For IP allowlists, this is a credible pre-authentication identity-spoofing path that bypasses the documented mitigation for the CVE-2026-33433/39858/54763 aliasing family.

2. Regulatory framing

Article Trigger (the fact in this item) Practical impact
DORA Art. 24: digital operational resilience testing — general requirements The bypass defeats a security control (aliasHeadersStrategy/underscoreHeadersStrategy/forwardedHeaders stripping) that operators deployed specifically as the documented mitigation for the CVE-2026-33433/39858/54763 aliasing family; the control's effectiveness must be re-verified after patching, not assumed. Re-test entrypoint sanitization controls post-upgrade to v3.7.13 — including trailer-channel probes — as part of resilience testing; do not carry forward prior test evidence for these controls.
DORA Art. 28: ICT third-party risk — general principles The exploit chain requires a downstream component that merges trailers into its header namespace (e.g. pre-fix libevent CVE-2026-63379, still shipped by Ubuntu 24.04; pre-fix blaze CVE-2026-73495); the risk is a property of the Traefik-plus-backend composition, not of either party alone. When Traefik fronts third-party-supplied backends, obtain from the provider an explicit statement of trailer-handling behaviour (merge vs. ignore) and patch state for the trailer-merge class; treat "backend merges trailers" as a material fact in third-party assessments.

No specific NIS2 article is directly engaged by this item: NIS2 Art. 21(2)(d) (supply chain security measures) and Art. 23 (incident reporting) are triggered by incidents and supplier compromises generally, and nothing in this item supplies a fact distinctive to those duties beyond what any vulnerability would.

3. Technical analysis & attack chain

Affected software: Traefik v3.2.0 – v3.7.12 (custom reverse proxy in pkg/proxy/httputil). Traefik v2 is not affected — it uses the Go standard library httputil.ReverseProxy, which does not forward request trailer values. End-of-life lines v3.2–v3.6 will not receive a fix on their own line. The FastProxy forwarding mode (opt-in [experimental] fastProxy) does not forward trailers and is not a value-carrying path. HTTP/3 (quic-go) trailer semantics are untested by the reporter.

Vulnerability mechanism. All four entrypoint sanitization handlers — removeAliasingHeaders, rejectAliasingHeaders, removeHeadersWithUnderscores, rejectHeadersWithUnderscores (pkg/server/server_entrypoint_tcp.go) — and the sibling forwardedheaders.DeleteXForwardedHeaders (pkg/middlewares/forwardedheaders/forwarded_header.go) iterate req.Header only and never scan req.Trailer, despite the handlers' own doc comments promising to cover "header and trailer". Go's HTTP server pre-fills declared trailer names into req.Trailer (with nil values) at parse time — fixTrailer in net/http/transfer.go for HTTP/1.1 chunked, the trailer: field of the initial HEADERS frame for HTTP/2 — so the entrypoint handlers structurally cannot see them, while Traefik's v3 proxy layer forwards them.

Confirmed attack chain (all steps measured by the reporter against source-built Traefik master @ 237f13c6, Go 1.27.0)

  1. Initial access. Unauthenticated client sends a request to a Traefik v3 entrypoint with the target name declared as a trailer — HTTP/1.1 chunked (Trailer: X_Auth_User header plus a trailer field line after the final 0 chunk) or HTTP/2 (trailer: in HEADERS). No opt-in option is required for the X-Forwarded-* path: stripping of client-supplied X-Forwarded-* is the default for untrusted clients.
  2. Sanitization bypass. reject mode does not return its documented 400; delete mode does not remove the name. Measured: header X_Auth_User400 (rejected as designed); trailer X_Auth_User200 with backend receiving TRAILERS: map[X_auth_user:[]]. Trailer X.Auth.User and trailer X-Forwarded-Prefix likewise pass. Trailer keys are canonicalized by textproto.CanonicalMIMEHeaderKey, which treats dashes — not underscores — as case separators, so the aliasing spelling survives as e.g. X_auth_user and remains detectable downstream.
  3. Value survival (body-buffering chains only). Trailer values are appended to req.Trailer only while the body is consumed. On the bare proxy path, Request.Clone runs at handler start before any body read, so the clone captures nil values and the trailer field line is omitted (HTTP/1.1) or delivered as an empty key (h2c) — name-level only. When a body-buffering middleware runs first, the order reverses: the retry middleware with status codes buffers via mirror.NewReusableRequestio.ReadAll(req.Body) (pkg/middlewares/retry/retry.go, pkg/server/service/loadbalancer/mirror/mirror.go), or the buffering middleware drains eagerly via oxy's multibuf.Newioutil.ReadAll (github.com/mailgun/multibuf buffer.go; unset limits fall back to 1 MB DefaultMemBytes). Values are then populated before the clone and travel to the backend with the attacker's chosen value. Buffering triggers for idempotent methods with status alone; POST additionally requires retryNonIdempotentMethod. The mirroring and failover services (failover with errors.status configured) use the same mirror.NewReusableRequest helper and are expected to share the behaviour — not measured.
  4. Downstream merge and impact. A backend that merges trailers into its header namespace acts on the smuggled name. Measured end-to-end against Ubuntu 24.04's libevent-2.1-7t64 2.1.12-stable-9ubuntu2 (pre-fix; merge fixed only in libevent 2.1.13) behind an ≈100-line evhttp server: header X-Forwarded-Prefix: admin403 DENIED (stripped by forwardedHeaders); identical name as a declared trailer through a retry chain → 200 ADMIN (prefix=admin). The same chain flips an X-Forwarded-For IP-allowlist pattern (/xff granting access on merged XFF == 203.0.113.7): header form denied, trailer form → 200 ADMIN. Presence-based authorization flips were also measured on an h2c merge backend (403 → 200 AUTHORIZED on trailer X_Auth_User with empty value).

Additional measured behaviours

  • Bait declaration (HTTP/1.1, buffered chains). Go's HTTP/2 server copies only pre-declared trailers, so undeclared fields never transit on h2 inbound. On HTTP/1.1, readTrailer parses the entire trailer section with no declaration filter; a zero-declaration request loses undeclared fields at Traefik's observability req.WithContext shallow copy, but declaring any clean name (e.g. Trailer: X-Dummy) keeps the map non-nil and the blind mergeSetHeader merge writes the undeclared field in at body EOF. Measured on the retry-buffered chain: backend receives map[X-Dummy:[1] X_auth_user:[attacker-value]]200 AUTHORIZED. Bare path unaffected.
  • Delete-mode stickiness. mergeSetHeader's non-nil branch is a blind maps.Copy (net/http/transfer.go), so a key deleted by a handler is re-added with its value at body EOF on HTTP/1.1; on HTTP/2 it stays deleted (copyTrailersToHandlerRequest checks the live map).
  • Value erasure primitive. A trailer-merging upstream folds the empty trailer over a legitimate identity header — X-Auth-User: admin becomes empty in the merged view. This typically denies rather than grants, but is an availability/erasure primitive.
  • Framing names. Trailer Content-Length, Transfer-Encoding, Trailer400 (Go rejects); Host and Connection pass name-level to the backend.
  • Regression-test gap. Traefik deliberately does not forward request trailers on the bare chain, locked by pkg/proxy/httputil/trailer_test.go and pkg/proxy/fast/trailer_test.go (added 86b5642f, 2026-06-25; extended d427dccf, 2026-06-29). The tests exercise only the bare chain; the buffered-chain value path defeats that locked invariant and neither test catches it.

Preconditions for exploitation: (1) reliance on entrypoint sanitization (delete/reject, or default X-Forwarded-* stripping); (2) the name delivered as a declared trailer, or — HTTP/1.1 buffered chains only — as an undeclared field riding a bait declaration; (3) for downstream impact, a backend that merges trailers into its header namespace (pre-fix libevent CVE-2026-63379, pre-fix blaze CVE-2026-73495, or custom code) or consumes trailer fields in a trust decision; (4) for the value-level path, a body-buffering middleware in the chain.

Confidence caveat. The full technical detail — root cause, mechanism, PoC matrix, and the libevent end-to-end demonstration — is single-sourced: it rests on the reporter's advisory (GHSA-v67p-phpq-fc8x) and its unpublished harness, with the GitHub advisory record (CVE-2026-88004 per the external source listing) carrying the same text. The vendor has shipped v3.7.13 as the fix, which corroborates the defect's existence, but the specific measured behaviours (bait declaration, delete-mode stickiness, XFF flip) have no independent reproduction in the available material. Verify in your own environment before enforcement action. Note also a CVE-numbering discrepancy: the verified reference data tracks the Traefik-side flaw as CVE-2026-54763 (CVSS 7.8 HIGH, CWE-178/CWE-290, EPSS 0%, not in KEV), while the GitHub advisory record is labelled CVE-2026-88004; we use the verified identifiers and scores throughout. The aliasing-family precedent (CVE-2026-33433, CVE-2026-39858, CVE-2026-54763) is corroborated by the related GHSA-x677-9fxg-v5c5 advisory.

4. Mitigation & containment

P1 — within 24 hours

  1. Inventory and patch. Identify all Traefik v3.2.0–v3.7.12 instances (including those embedded in Kubernetes ingress deployments) and upgrade to v3.7.13 (https://github.com/traefik/traefik/releases/tag/v3.7.13). Instances on end-of-life v3.2–v3.6 lines cannot be patched in place — plan the jump to v3.7.13. Traefik v2 instances are not affected by this flaw and need no action for it.
  2. Determine exposure to the value-level path. Grep dynamic configuration for body-buffering middleware on any internet-facing router: retry middleware with a status list (including the documented example pattern status = ["400","500-599"]), and the buffering middleware. Also check mirroring services and failover services with errors.status configured (same mirror.NewReusableRequest helper; expected to share the behaviour). Any such chain in front of a trailer-merging backend is the highest-risk configuration.
  3. Determine backend trailer behaviour. Establish whether backends behind Traefik merge trailers into their header namespace. Known merge components: libevent < 2.1.13 (Ubuntu 24.04 ships 2.1.12-stable-9ubuntu2 — check dpkg -l libevent-2.1-7t64) and pre-fix blaze/http4s (CVE-2026-73495, fixed ef3e666). Patch or upgrade merge components in parallel; the Traefik fix stops value forwarding, but the backend-side merge flaw (CVE-2026-63379) remains exploitable by any other front-end that forwards trailers.

P2 — within 72 hours

  1. Interim hardening for instances that cannot be patched immediately. Where upgrade is delayed, apply defence-in-depth at the backend: ensure backends ignore request trailers in trust decisions, or strip/ignore trailer fields at the backend's HTTP layer. Do not rely on reject mode — it demonstrably does not fire on trailers pre-patch.
  2. Verify the fix. Post-upgrade, replay the reporter's probe: send a chunked HTTP/1.1 request with Trailer: X_Auth_User and a trailer field line X_Auth_User: attacker-value (with a retry middleware in the chain) and confirm the backend no longer receives the value. Confirm legitimate declared trailer names still forward (the fix stops values, not names, per RFC 9110 §6.6.2 — gRPC grpc-status is unaffected).
  3. Review trust in X-Forwarded-For. Any IP-allowlist or geo-blocking logic keyed on X-Forwarded-For at trailer-merging backends was spoofable pre-patch. Review logs for the bypass pattern (see §5/§6) and reassess whether decisions made on XFF during the exposure window need retrospective review.

P3 — within 7 days

  1. Re-test entrypoint controls per DORA Art. 24, including trailer-channel probes in both delete and reject modes and on buffered chains, and record the result as new evidence rather than reusing pre-patch test artefacts.
  2. Third-party confirmation per DORA Art. 28: for backends supplied by third parties, obtain written confirmation of trailer-handling behaviour and patch state for the CVE-2026-63379 merge class.
  3. Check for the sibling flaws in the same deployment: the reporter's chain-of-conditions and the related corpus show the aliasing family (CVE-2026-33433/39858/54763) and path-traversal route bypasses (GHSA-rhg6-2vjh-j5qc ReplacePathRegex, fixed v2.11.52/v3.6.23/v3.7.7; GHSA-7qf5-7ppr-87v8 and GHSA-8rxv-jg7p-wvg3 ingress-nginx RewriteTarget, fixed v3.7.8; GHSA-xf64-8mw2-4gr2 StripPrefix, fixed v2.11.48/v3.6.19/v3.7.3; GHSA-f52w-8j3h-j724 rootless request-target, fixed v2.11.57/v3.7.13) — upgrading to v3.7.13 addresses the trailer flaw and the rootless request-target flaw in one move.

5. Indicators of compromise

No atomic indicators of compromise (hashes, domains, IPs) are available in the source material. This is a vulnerability advisory with a researcher-built PoC; no attacker infrastructure or malware artefacts are described.

Behavioural indicators

Behaviour Where to observe Confidence
Inbound requests with a Trailer: request header declaring names such as X_Auth_User, X.Auth.User, X-Forwarded-Prefix, X-Forwarded-For (or any underscore/dot-variant of a trusted proxy header) Traefik access logs, upstream WAF/load-balancer logs, full-packet capture at the edge High — this is the delivery mechanism itself; legitimate trailer use for these names is rare
HTTP/1.1 chunked requests carrying trailer field lines matching sanitized/trusted header names after the terminal 0 chunk Edge packet capture, WAF with trailer inspection High
HTTP/2 requests with a trailer: field in the initial HEADERS frame naming trusted/aliasing headers HTTP/2-aware edge telemetry Medium — requires h2 frame-level visibility
Bait-declaration pattern: Trailer: X-Dummy (or any clean name) combined with undeclared trailer fields in the trailer section Edge packet capture on buffered chains Medium — single-sourced; verify before enforcement
Authorization decisions flipping on trailer-merged identity keys at backends (e.g. 403 → 200 on presence of X_auth_user, admin grants via X-Forwarded-Prefix: admin) Backend application/auth logs, particularly where X-Forwarded-For IP allowlists are enforced High for the mechanism; environment-dependent for observability

6. Detection

The sources provide configuration artefacts and request-level behaviours but no file-based threat artefacts (no malware strings, mutexes, or file paths), so a YARA rule is not appropriate. The following Sigma-style rule targets the observable request pattern at proxy/edge logs.

title: Traefik Trailer-Based Trusted Header Name Smuggling (CVE-2026-54763)
id: 8f3a1c92-4b7d-4e2a-9c15-6d0e7f8a9b21
status: experimental
description: >
  Detects inbound requests declaring sanitized or trusted header names as HTTP
  trailers, the delivery mechanism for the Traefik entrypoint sanitization
  bypass (GHSA-v67p-phpq-fc8x). Covers aliasing spellings (X_Auth_User,
  X.Auth.User) and trusted names (X-Forwarded-Prefix, X-Forwarded-For).
references:

  - https://github.com/advisories/GHSA-v67p-phpq-fc8x
author: Adverse Trace
date: 2026-09-11
logsource:
  category: proxy
detection:
  selection_trailer_header:
    http.request_header_trailer|contains:

      - 'X_Auth_User'
      - 'X.Auth.User'
      - 'X-Forwarded-Prefix'
      - 'X-Forwarded-For'
  condition: selection_trailer_header
falsepositives:

  - Legitimate applications using HTTP trailers with these specific names are rare; gRPC uses grpc-status/grpc-message, which do not match
level: high

Note: detection requires edge telemetry that captures the Trailer request header or trailer field lines; Traefik's own access log does not record trailer content, and the related GHSA-f52w-8j3h-j724 advisory demonstrates that Traefik access logging can misrepresent request targets — do not treat Traefik access logs as authoritative evidence of absence.

CVE assessment

2 referenced CVEs

CVE CVSS Exploited EPSS Summary
CVE-2026-54763 7.8 High 0% Traefik is an HTTP reverse proxy and load balancer. Prior to v2.11.51, v3.6.22, and v3.7.6, Traefik's BasicAuth, DigestAuth, an…
CVE-2026-63379 6.3 Medium 1% Libevent is an event notification library. Prior to 2.1.13 and 2.2.2-alpha, libevent processes chunked HTTP trailers in http.c…

7. Sources

  • GitHub Security Advisories — "Traefik entrypoint header-name sanitization bypassed via request trailers" (GHSA-v67p-phpq-fc8x) — https://github.com/advisories/GHSA-v67p-phpq-fc8x — 2026-09-10
  • GitHub Advisory Database record for the same advisory (listed as CVE-2026-88004) — https://github.com/advisories/GHSA-v67p-phpq-fc8x — accessed 2026-09-11
  • Traefik v3.7.13 release (vendor fix) — https://github.com/traefik/traefik/releases/tag/v3.7.13
  • GitHub Security Advisories — "Incomplete fix for CVE-2026-33433 + CVE-2026-39858 cross-cohort: headerField underscore-variant identity spoofing in BasicAuth / DigestAuth / ForwardAuth" (GHSA-x677-9fxg-v5c5, aliasing-family precedent) — https://github.com/advisories/GHSA-x677-9fxg-v5c5
  • GitHub Security Advisories — "Traefik: Rootless HTTP/1 request-target routes as '/' but is forwarded verbatim" (GHSA-f52w-8j3h-j724, fixed in the same v3.7.13 release) — https://github.com/advisories/GHSA-f52w-8j3h-j724

8. Adverse Trace position

We assess this as a high-severity configuration-control bypass (CVE-2026-54763, CVSS 7.8 HIGH, not in CISA KEV, EPSS 0%) with material but conditional impact: the name-level bypass affects any v3.2.0–v3.7.12 deployment relying on entrypoint sanitization, while the more dangerous value-level identity spoofing requires both a body-buffering middleware (retry with status, or buffering — mainstream, documented features) and a trailer-merging backend (CVE-2026-63379-class, CVSS 6.3 MEDIUM, EPSS 1%), a combination plausibly present in financial-services estates where Traefik fronts libevent-based or custom C/Go services and where X-Forwarded-For IP allowlists are common. Exploitation is unauthenticated and leaves no malware artefacts, so compromise is only visible through request-level telemetry — clients should assume under-detection and treat the exposure window (any time on an affected version with a buffering chain) as unverified rather than clean. The absence of KEV listing and the 0–1% EPSS scores indicate no observed in-the-wild exploitation as of the advisory data; this is a patch-on-schedule issue, not an emergency, but the v3.7.13 upgrade should be pulled into the normal cycle immediately and the EOL v3.2–v3.6 jump planned now. The technical detail is single-sourced to the reporter's advisory with vendor fix as corroboration; we will monitor for independent reproduction, a CISA KEV listing, or exploitation reporting, and will reissue if the EPSS or KEV position moves.


Read the original source →

Published via PulseTrace — Adverse Trace threat intelligence.

Post this to LinkedIn
Formatting is converted automatically — headings, bullets, a link back & hashtags. Paste straight in.
J
Jeff Davies