# Traefik HTTP/3 Backend NTLM Connection Reuse

Traefik's HTTP/3 path skipped AddTransportOnContext, so kerberosRoundTripper fell back to a shared backend pool, letting an unauthenticated HTTP/3 client inherit a victim's NTLM/Negotiate-authenticated backend connection.

- Payout: Research
- Severity: critical
- Program: Traefik
- Found by: OneZ3r0
- Disclosed: 2026-09-10
- CVE: CVE-2026-88007
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-qqjf-53cj-pwvv
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-qqjf-53cj-pwvv
- Tags: area:cloud domain:infra impact:data-leak impact:integrity kind:research platform:ghsa sev:critical tech:go technique:regression technique:source-review vuln:access-control vuln:auth-bypass

**Target:** HTTP/3 entrypoint reverse proxy to NTLM/Negotiate backend
**Root cause:** HTTP/3 ConnContext only propagated the TLS options name and never called service.AddTransportOnContext, so the per-connection stickyRoundTripper holder was absent and kerberosRoundTripper fell back to the shared OriginalRoundTripper instead of a per-frontend-connection backend pool.
**Steps:**
1. Enable HTTP/3 on a Traefik entrypoint routing to a backend that binds identity to a persistent HTTP/1.1 connection via NTLM/Negotiate, with backend keep-alive.
2. Victim authenticates through Traefik over HTTP/3; kerberosRoundTripper sees `WWW-Authenticate` NTLM/Negotiate but has no transportKey in context, so no dedicated RoundTripper is stored.
3. Second unauthenticated HTTP/3 client sends a request with no `Authorization` header to the same route.
4. Traefik assigns the same backend TCP connection already authenticated as the victim; attacker reads `resource=secret actor=victim`.
5. Attacker issues `/transfer?to=attacker&amount=5000`, executed as `actor=victim` on the same backend connection identifier.
6. Control: repeat over HTTPS/HTTP/1.1 with a fresh attacker connection; it correctly returns `401`.
7. Repro: `./run.sh` (or `PRODUCT_COMMIT=f2d0794417e4d06343e6e7c4722143f5b34bee45 ./run.sh`) builds the pinned commit and runs the verifier.
**How found:** Protocol-parity review: compared the TCP entrypoint's ConnContext (which calls service.AddTransportOnContext to install the stickyRoundTripper holder) against the HTTP/3 entrypoint's ConnContext, which only calls tcp.AddTLSOptionsNameInContext. Traced kerberosRoundTripper's fallback to OriginalRoundTripper when transportKey is missing, then built a synthetic NTLM-like backend to confirm cross-client identity reuse over HTTP/3 versus correct isolation over HTTP/1.1.
**Exploitation:** Attacker needs only network reach to the same HTTP/3 route as the victim. After the victim authenticates to the NTLM/Negotiate backend, the attacker's separate HTTP/3 client is handed the victim-authenticated backend TCP connection, inheriting identity to read victim-only data and perform state-changing requests (transfer of 5000 to attacker) without any credentials.
**Insight:** When a proxy special-cases connection-bound auth (NTLM/Negotiate) via per-connection context state, audit every alternate listener/protocol path (HTTP/3, h2c, raw TCP) for the same context initialization; a missing context value silently degrades to a shared pool rather than erroring.

## Proof of concept (copied exactly from the original report)

**run.sh invocation of the PoC verifier**

```
PRODUCT_COMMIT=f2d0794417e4d06343e6e7c4722143f5b34bee45 ./run.sh
```

**Attacker transfer request as victim**

```
the attacker performs `/transfer?to=attacker&amount=5000` as `actor=victim`
```

