Jul 22, 2026·6 min read·44 visits
Unauthenticated remote attackers can trigger a heap memory leak in Eclipse Jetty by sending requests that yield zero-byte reads (e.g., Expect: 100-Continue handshakes resulting in early 404 responses). Over repeated connections, this exhausts the RetainableByteBufferPool, leading to an OutOfMemoryError and service crash.
Eclipse Jetty is subject to an uncontrolled resource consumption vulnerability in its HTTP connection handling component. When processing certain HTTP request sequences, such as those invoking the Expect: 100-Continue handshake under specific network constraints, the server fails to return allocated buffers to its central pool. Over time, this leads to buffer pool exhaustion and a complete denial of service via memory starvation.
The vulnerability exists within the HTTP connection handling implementation of Eclipse Jetty, specifically inside the HttpConnection.fillRequestBuffer() method. Eclipse Jetty utilizes an internal buffer recycling mechanism to minimize memory fragmentation and reduce garbage collection overhead during high-throughput network operations. This system depends on the proper allocation and subsequent reclamation of buffer instances.
In affected versions, network conditions or specific application behaviors can cause the connection layer to allocate a buffer but abandon it without triggering the appropriate release cycle. The attack surface is exposed to any remote client capable of establishing a TCP connection to the Jetty HTTP connector. No authentication or specific privileges are required to reach the vulnerable code path.
Because the resource leak occurs within the server's core network transport layer, the degradation is cumulative. Every instance of an abandoned buffer reduces the available capacity of the shared buffer pool. Under sustained or repeated invocation, the pool is depleted, preventing the server from accepting new connections and ultimately triggering an unrecoverable system failure.
The root cause of CVE-2024-7708 lies in the logical control flow of org.eclipse.jetty.server.HttpConnection.fillRequestBuffer(). To optimize memory performance, Jetty utilizes RetainableByteBuffer objects obtained from a central RetainableByteBufferPool. The connection handler is designed to acquire a buffer from this pool, read incoming network packets via the underlying endpoint, and release the buffer once parsing is complete or when the connection state transitions.
A memory leak occurs when the server attempts to read from a connection's endpoint and the operation returns zero bytes, or when a non-I/O exception is thrown during processing. For example, if a client sends request headers indicating a payload is forthcoming (such as a Content-Length or chunked transfer encoding) but the connection is closed or stalled before payload bytes arrive, the endpoint read returns zero. In this state, the original implementation branched past the cleanup code, failing to call releaseRequestBuffer().
Furthermore, the error handling framework in the vulnerable versions was overly restrictive. The try-catch block surrounding the endpoint fill operation only caught IOException. If an unhandled RuntimeException or other error occurred during packet decoding or header parsing, the execution skipped the recovery block entirely, leaving the acquired RetainableByteBuffer permanently allocated in the pool.
An analysis of the vulnerability patch in HttpConnection.java clarifies the precise location of the logical omission. The code block below compares the vulnerable handling with the corrected resource release logic.
// Vulnerable Flow vs Patched Flow in HttpConnection.java
// Prior logic: only added bytes if filled > 0, otherwise branched to atEOF() without releasing buffer
if (filled > 0)
{
bytesIn.add(filled);
}
else
{
if (filled < 0)
_parser.atEOF();
// FIX: Explicitly release the request buffer back to the pool if no bytes were read
releaseRequestBuffer();
}
if (LOG.isDebugEnabled())
LOG.debug("{} filled {} {}", this, filled, _retainableByteBuffer);
return filled;
}
// FIX: Broadened catch block from IOException to Throwable to intercept all runtime exceptions
catch (Throwable x)
{
if (LOG.isDebugEnabled())
LOG.debug("Unable to fill from endpoint {}", getEndPoint(), x);
_parser.atEOF();
// FIX: Ensure cleanup occurs and resource is released on any thrown exception
if (_retainableByteBuffer != null)
{
_retainableByteBuffer.clear();
releaseRequestBuffer();
}
return -1;
}The original implementation failed to address the scenario where filled == 0. In that condition, the connection did not call releaseRequestBuffer(), leading to an accumulation of retained buffers in memory. The corrected code ensures that any non-positive read outcome triggers an immediate release of the buffer. By broadening the exception handler to catch Throwable instead of just IOException, the patch prevents memory leaks stemming from unexpected application-level runtime failures.
Exploitation of CVE-2024-7708 requires an attacker to initiate HTTP transactions that result in empty read operations or early connection termination before the request body is transmitted. The most reliable method to achieve this condition involves using the Expect: 100-Continue HTTP header.
In a standard scenario, a client sends an HTTP request header containing Expect: 100-Continue to verify if the server will accept the payload. If the requested URL does not exist or triggers an immediate validation failure, Jetty generates a 404 Not Found or 400 Bad Request response prior to reading the request body. If the connection is then terminated, the server attempts to parse the remaining request envelope, resulting in zero bytes read and triggering the leak condition.
An attacker can automate this interaction by establishing multiple parallel TCP connections, sending headers containing Expect: 100-Continue to an invalid endpoint, and closing the write end of the socket. Because each transaction permanently leaks one RetainableByteBuffer in the shared RetainableByteBufferPool, executing this pattern at scale will steadily exhaust the server heap, leading to total service degradation without requiring high bandwidth.
The impact of this vulnerability is categorized as a high-severity Denial of Service (DoS). Because the leak targets the heap-allocated direct byte buffers used for network transport, memory exhaustion affects the entire Java Virtual Machine (JVM) hosting the Jetty container.
Once the RetainableByteBufferPool is fully depleted, the application server is unable to process any new incoming network requests. This results in standard socket connection timeouts for legitimate clients. If the leak continues, the JVM eventually throws an OutOfMemoryError (OOM), leading to abnormal termination of the server process.
This vulnerability has no direct impact on data confidentiality or integrity. It cannot be leveraged to execute arbitrary code or bypass security authorization controls. However, due to the ease of triggering the leak and the lack of authentication requirements, the potential for service disruption is significant.
The definitive resolution for this vulnerability is to upgrade the Eclipse Jetty deployment to a patched release. All deployments using Jetty 10 or Jetty 11 should be transitioned to the corrected versions.
If an immediate upgrade is not feasible, operators can apply temporary configuration mitigations to reduce exposure. Implementing reverse proxies or Web Application Firewalls (WAFs) to filter or drop requests containing Expect: 100-Continue headers can mitigate the primary vector. Additionally, reducing the maximum idle timeouts on Jetty connectors limit the lifetime of stalled connections, reducing the rate of buffer accumulation.
Administrators should also configure JVM monitoring tools to track the utilization of Direct ByteBuffers and the JVM heap. A continuous upward trend in buffer allocation that does not return to baseline during idle periods is a strong indicator of active exploitation or unchecked memory leaks.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Jetty Eclipse Foundation | >= 10.0.7, < 10.0.23 | 10.0.23 |
Jetty Eclipse Foundation | >= 11.0.7, < 11.0.23 | 11.0.23 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-400, CWE-401 |
| Attack Vector | Network (AV:N) |
| CVSS Severity | 7.5 (High) |
| EPSS Score | 0.00252 |
| Impact | Denial of Service (DoS) |
| Exploit Status | Proof of Concept (PoC) available |
| CISA KEV Status | Not Listed |
The system does not limit or properly release allocated memory buffers, enabling remote attackers to consume all available memory resources.
A path traversal vulnerability (CWE-22) in Contao CMS allows unauthenticated remote attackers to bypass directory boundary restrictions in ImagesController and access files within the project directory.
Contao Open Source CMS versions 4.0.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 contain a Cross-Site Request Forgery (CSRF) vulnerability in backend parameter handling. The `RequestTokenListener` component validates anti-CSRF tokens solely for HTTP POST requests, while GET-based declarative guards run only when an `act` parameter is present in the query string. Consequently, custom backend actions dispatched via alternative parameters such as `key=` can execute without CSRF token verification when triggered by an authenticated user.
Contao CMS versions 4.1.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 fail to validate form submission tokens and enforce rate limiting when processing activation email resend requests via HTTP POST, enabling resource exhaustion and account state enumeration.
An information disclosure vulnerability in Contao CMS allows unauthenticated site visitors to view protected page titles, URLs, and text excerpts through search queries when protected page indexing is disabled after previously being enabled.
In Vikunja prior to version 2.6.0, relation creation via the CalDAV endpoint fails to invoke the TaskRelation.CanCreate authorization check. This missing access control allows an authenticated user to establish unauthorized relationships and perform write operations against any task, provided its unique identifier (UID) is known.
A cross-project information disclosure vulnerability in Vikunja allows authenticated users with read access to one project to view private task details from unauthorized projects via subtask expansion parameters.