CVE-2026-19204
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Eclipse Jetty is an open-source Java web server and Jakarta Servlet container, widely deployed both standalone and embedded inside Java applications and frameworks. Its websocket-core-common module implements WebSocket frame parsing for the Jetty native WebSocket API, the javax.websocket and jakarta.websocket standard APIs, and Jetty's WebSocket client.
A denial of service vulnerability (CVE-2026-19204) has been identified in Eclipse Jetty's WebSocket frame parser, which allows any peer that completes a WebSocket handshake to exhaust the server's heap. The parser allocates a buffer of the size declared in a frame's payload length before it validates the frame's opcode. A frame carrying a reserved, unknown opcode is neither a data frame nor a control frame, so with auto-fragmentation enabled (the default) it bypasses the configured maximum frame size entirely, and the parser allocates the full attacker-declared length, up to roughly 2 GiB per frame, for a frame it will later reject. A remote attacker can repeat this over many connections until the JVM runs out of memory.
Under CWE-770 (Allocation of Resources Without Limits or Throttling), MITRE classifies this weakness as one where "The product allocates a reusable resource or group of resources on behalf of an actor without imposing any intended restrictions on the size or number of resources that can be allocated."
This issue affects Eclipse Jetty 10.0.0 through 10.0.31.1 and 11.0.0 through 11.0.31 on the lines supported by NES for Jetty, as well as the maintained 12.0.x and 12.1.x lines before 12.0.38 and 12.1.12. Jetty 9.4.x is not affected: its WebSocket parser rejects unknown opcodes on the first byte of a frame, before the payload length is read.
Details
Module Info
- Product: Eclipse Jetty
- Affected packages: org.eclipse.jetty.websocket:websocket-core-common
- Affected versions: >=10.0.0 <10.0.32, >=11.0.0 <11.0.32, >=12.0.0 <12.0.38, >=12.1.0 <12.1.12
- GitHub repository: https://github.com/jetty/jetty.project
- Published packages: https://central.sonatype.com/artifact/org.eclipse.jetty.websocket/websocket-core-common
- Package manager: Maven
- Fixed in: NES for Jetty 10.0.32 and 11.0.32 (upstream community-supported lines fixed in Eclipse Jetty 12.0.38 and 12.1.12)
Vulnerability Info
This High-severity vulnerability is found in the websocket-core-common package in multiple versions of Eclipse Jetty on the 10.0.x, 11.0.x, 12.0.x and 12.1.x lines. It is reachable by any WebSocket peer, client or server, that completes an upgrade handshake with an endpoint built on Jetty's websocket-core stack; no authentication or user interaction is required.
The parser in org.eclipse.jetty.websocket.core.internal.Parser is a state machine that reads the first byte of a frame, then the payload length, then the masking key and finally the payload. In the affected versions the START state only stores the first byte and moves on; the opcode it carries is not checked:
case START:
{
// peek at byte
firstByte = buffer.get();
state = State.PAYLOAD_LEN;
break;
}
Once the extended payload length has been read, and before any payload bytes are consumed, checkFrameSize() is supposed to enforce the configured limit. It distinguishes only control frames from everything else, and for everything else it applies the maximum frame size only when auto-fragmentation is disabled:
if (OpCode.isControlFrame(opcode))
{
...
}
else
{
long maxFrameSize = configuration.getMaxFrameSize();
if (!configuration.isAutoFragment() && maxFrameSize > 0 && payloadLength > maxFrameSize)
throw new MessageTooLargeException("Cannot handle payload lengths larger than " + maxFrameSize);
}
Auto-fragmentation is on by default. The intent is safe for genuine data frames, because parsePayload() splits any TEXT, BINARY or CONTINUATION frame larger than the maximum frame size into fragments instead of buffering it. An unknown opcode, however, is not a data frame, so neither fragmentation path applies. When such a frame arrives with more payload declared than is present in the buffer, the parser falls through to aggregating the partial payload and allocates the declared size in one step:
// No space in the buffer, so we have to copy the partial payload.
// The size of this allocation is limited by the maxFrameSize.
aggregate = bufferPool.acquire(payloadLength, false);
The comment is not true for unknown opcodes: nothing has bounded payloadLength except the parser's refusal of values above Integer.MAX_VALUE. The opcode is finally validated in newFrame(), which throws ProtocolException("Unknown opcode") only after the complete payload has been received, long after the allocation. A single frame whose first byte carries a reserved opcode (0x3 to 0x7 or 0xB to 0xF), whose length marker is 0x7F and whose 64-bit length is just under Integer.MAX_VALUE, sent as a partial frame, therefore forces an allocation of that size; repeating it across connections exhausts the heap and takes the server down with an OutOfMemoryError. Deployments that disable auto-fragmentation are not exposed to this path, because the maximum frame size check above then applies to these frames.
Jetty 9.4.x uses an earlier, separate WebSocket implementation whose parser checks OpCode.isKnown() on the first byte of every frame and throws before the payload length is parsed, so the unknown-opcode flaw described by this CVE does not exist there.
Mitigation
Jetty 10.0.x and 11.0.x are past community End-of-Life and no longer receive open-source updates to address this issue.
Users of the affected components should apply one of the following mitigations:
- Upgrade Eclipse Jetty to a currently supported release line (12.0.x or 12.1.x) that contains the fix, first shipped in Eclipse Jetty 12.0.38 and 12.1.12.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.
Credits
- Arthur Chan (finder)
- David Korczynski (finder)
- Adam Korcz (finder)