CVE-2026-12611
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 http2-common and http2-server modules implement the HTTP/2 protocol for server connectors, including the per-connection session that multiplexes streams and the flusher that writes frames to the network.
A denial of service vulnerability (CVE-2026-12611) has been identified in Eclipse Jetty's HTTP/2 implementation, which allows an unauthenticated remote client to leave server threads blocked forever. By interleaving RST_STREAM and GOAWAY frames while a connection is being torn down, the client races the session termination logic so that the flusher's "closed" marker is cleared after it has already been set. Frames queued for that connection from then on are accepted but never written or failed, so every thread performing a blocking response write on one of its streams waits indefinitely. Repeating the sequence exhausts the server thread pool and the whole server stops responding.
MITRE's CWE-400 (Uncontrolled Resource Consumption) describes this weakness as one where "The product does not properly control the allocation and maintenance of a limited resource."
This issue affects Eclipse Jetty 9.4.36 through 9.4.63, 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.11.
Details
Module Info
- Product: Eclipse Jetty
- Affected packages: org.eclipse.jetty.http2:http2-common, org.eclipse.jetty.http2:http2-server
- Affected versions: >=9.4.36 <9.4.64, >=10.0.0 <10.0.32, >=11.0.0 <11.0.32, >=12.0.0 <12.0.38, >=12.1.0 <12.1.11
- GitHub repository: https://github.com/jetty/jetty.project
- Published packages: https://central.sonatype.com/artifact/org.eclipse.jetty.http2/http2-common
- Package manager: Maven
- Fixed in: NES for Jetty 9.4.64, 10.0.32 and 11.0.32 (upstream community-supported lines fixed in Eclipse Jetty 12.0.38 and 12.1.11)
Vulnerability Info
This High-severity vulnerability is found in the http2-common package in all affected versions of Eclipse Jetty. It is reachable only on server connectors with HTTP/2 enabled (h2 over TLS with ALPN, or h2c); HTTP/1.1-only deployments are not exposed.
HTTP2Flusher is the component that serializes frames onto the connection. Its terminated field doubles as the flusher's "closed" marker: append() enqueues a new entry only while terminated is null, and otherwise fails the entry immediately so the caller is released with an exception. Two paths set the marker. The first is the write-failure callback, which records the failure and fails every queued entry. The second is terminate(Throwable cause), which unconditionally overwrites the field with whatever it is given:
void terminate(Throwable cause)
{
Throwable closed;
synchronized (this)
{
closed = terminated;
terminated = cause;
...
}
if (closed == null)
iterate();
}
terminate is called from the session's close state machine once the last stream of a closing session has been destroyed. That final step reads the session's recorded failure outside the lock and passes it straight through:
private void terminate(GoAwayFrame frame)
{
...
HTTP2Session.this.terminate(failure);
notifyClose(HTTP2Session.this, frame, Callback.NOOP);
}
The failure field is only assigned on failure paths such as idle timeouts, session failures and write failures. On the ordinary GOAWAY exchange it stays null, and the terminating action is scheduled to run as soon as the stream count reaches zero, which the client drives by resetting its streams. A client that issues requests, sends RST_STREAM for them and then sends GOAWAY while closing its side can therefore make the session call terminate(null) after the write-failure callback has already set terminated to a real exception. Because closed is non-null at that point the flusher does not iterate, and terminated is now null again: the flusher looks open, but its processing loop has already failed and will never run.
From then on append() accepts entries for the dead connection and nobody completes their callbacks. On the 9.4.x, 10.0.x and 11.0.x lines, servlet response writes travel through HttpOutput into a SharedBlockingCallback that blocks the request thread until the HTTP/2 layer completes the write. Each response written on one of these streams pins a QueuedThreadPool thread permanently. Repeating the sequence across connections drains the pool, at which point the server no longer accepts or handles any request. The impact is limited to availability; no data is exposed or modified.
Mitigation
Jetty 9.4.x, 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.11.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.
Credits
- No finder is publicly credited for this vulnerability.