CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-1605
7.50.04%

CVE-2026-1605: Native Memory Leak in Eclipse Jetty GzipHandler

Alon Barad
Alon Barad
Software Engineer

Mar 5, 2026·6 min read·5 visits

PoC Available

Executive Summary (TL;DR)

Eclipse Jetty fails to release native memory for Gzip-compressed requests when the response is not compressed. Attackers can exhaust server memory by sending compressed requests without the 'Accept-Encoding: gzip' header.

A high-severity resource management vulnerability exists in Eclipse Jetty versions 12.0.0 through 12.0.31 and 12.1.0 through 12.1.5. The GzipHandler component fails to correctly release native memory resources associated with the zlib Inflater when processing compressed requests if the corresponding response is not compressed. This allows unauthenticated remote attackers to trigger a native memory leak, leading to Denial of Service (DoS) via application crash or OOM termination.

Vulnerability Overview

Eclipse Jetty is a widely used Java-based web server and servlet container. The vulnerability resides in the GzipHandler, a component responsible for dynamically compressing responses and decompressing requests. When handling HTTP requests with a Content-Encoding: gzip header, Jetty utilizes the java.util.zip.Inflater class to decompress the request body. Note that Inflater allocates native (off-heap) memory via the zlib library, which is not directly managed by the Java Garbage Collector.

In affected versions, a logic error in the request lifecycle management prevents the explicit release of these native resources under specific conditions. While the Java wrapper objects are eventually garbage collected, the underlying native memory blocks allocated by zlib remain explicitly allocated until the end() method is called. This discrepancy leads to a native memory leak.

This vulnerability is classified as CWE-400 (Uncontrolled Resource Consumption) and CWE-401 (Missing Release of Memory after Effective Lifetime). It poses a significant availability risk, as a relatively low volume of malicious traffic can exhaust the available native memory of the host system, causing the operating system to terminate the Java process.

Root Cause Analysis

The root cause of CVE-2026-1605 is an asymmetric resource lifecycle management flaw within GzipHandler.java. The handler manages two distinct operations: inflating (decompressing) the request and deflating (compressing) the response. These operations utilize Inflator and Deflater objects, respectively, which are pooled to reduce allocation overhead.

In the vulnerable implementation, the cleanup logic for the Inflator (used for the request) was inadvertently coupled to the response compression logic. When a request required inflation, a GzipRequest object was created, leasing an Inflator from the pool. The return of this resource to the pool was handled by the destroy() method.

However, the call to destroy() was only scheduled if the response also required compression. The code relied on a wrapper class GzipResponseAndCallback to handle the completion callback and trigger cleanup. If the response did not trigger compression—for instance, if the client omitted the Accept-Encoding: gzip header or if the response MIME type was excluded—this wrapper was never instantiated. Consequently, the completion callback passed to the next handler in the chain did not include the destroy() hook, and the Inflator was never returned to the pool or released.

Code Analysis

The vulnerability exists in the handle method of GzipHandler.java. The fix involves decoupling the request cleanup from the response configuration. Below is a comparison of the logic before and after the patch.

Vulnerable Logic: In the vulnerable code, the callback (which signifies request completion) is only wrapped if tryDeflate (response compression) is true.

// Vulnerable: Cleanup logic is conditional on response compression
if (tryDeflate) {
    // GzipResponseAndCallback handles both response compression
    // AND request cleanup (calling gzipRequest.destroy())
    callback = new GzipResponseAndCallback(handler, request, response, callback);
} 
// If tryDeflate is false, 'callback' remains unwrapped.
// The gzipRequest is created, but its destroy() method is never scheduled.

Patched Logic (Commit a9e16433): The fix introduces a dedicated cleanup wrapper using Callback.from. This ensures that gzipRequest::destroy is called regardless of whether the response is compressed.

if (inflatable && tryInflate || etagMatches) {
    // ... GzipRequest instantiation ...
    GzipRequest gzipRequest = new GzipRequest(request, _inflaterPool, ...);
    request = gzipRequest;
 
    // FIX: Unconditionally wrap the callback to ensure resource release.
    // This ensures destroy() is called even if response compression is skipped.
    callback = Callback.from(callback, gzipRequest::destroy);
}

This change ensures that every Inflater leased from the pool is guaranteed to be returned when the request processing completes, eliminating the leak path.

Exploitation Methodology

Exploiting this vulnerability requires sending a specific sequence of HTTP headers that triggers request decompression while bypassing response compression. No authentication is required.

Attack Prerequisites:

  1. Network access to a Jetty server with GzipHandler enabled (enabled by default in many configurations).
  2. Ability to send POST or PUT requests with a body.

Exploit Steps:

  1. Construct Payload: Create a compressed body payload (e.g., using gzip).
  2. Craft Request: Send an HTTP POST request with the header Content-Encoding: gzip.
  3. Suppress Response Compression: Crucially, omit the Accept-Encoding: gzip header. This forces the server to skip the response compression logic, triggering the vulnerable code path where the cleanup callback is missed.
  4. Repeat: Execute this request in a loop. Each request leaks one Inflator instance (approximately 32KB-64KB of native memory depending on zlib settings, plus the overhead of the Java wrapper).

Proof of Concept (Conceptual):

# Compress a dummy payload
echo "data" | gzip > payload.gz
 
# Send request causing leak
# Note: No Accept-Encoding header is sent
curl -X POST -H "Content-Encoding: gzip" --data-binary @payload.gz http://target-server/

Continued execution of this loop will cause the process Resident Set Size (RSS) to grow until the operating system invokes the OOM killer.

Impact Assessment

The primary impact of CVE-2026-1605 is Denial of Service (DoS). Unlike heap-based memory leaks which result in a java.lang.OutOfMemoryError: Java heap space (often recoverable or catchable), this vulnerability exhausts native memory.

Consequences:

  1. Process Termination: The Operating System will terminate the JVM process when it exceeds the available system memory or cgroup limits (in containerized environments like Kubernetes).
  2. Monitoring Evasion: Standard JVM heap monitoring tools (e.g., JMX heap usage) will not show a spike in memory usage, as the leak is off-heap. This complicates detection and root cause analysis for operations teams.
  3. Resource Depletion: In a shared environment, the memory exhaustion may affect other services running on the same host.

Severity Metrics:

  • CVSS v3.1: 7.5 (High)
  • Vector: AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
  • Availability: High (Complete loss of service availability).
  • Confidentiality/Integrity: None.

Remediation & Mitigation

The only complete fix is to upgrade the Eclipse Jetty components to a patched version. The fix was backported to the supported 12.0 and 12.1 branches.

Patched Versions:

  • Jetty 12.0.x: Upgrade to 12.0.32 or later.
  • Jetty 12.1.x: Upgrade to 12.1.6 or later.

Workarounds: If an immediate upgrade is not feasible, the following temporary mitigations apply:

  1. Disable GzipHandler: If request/response compression is not strictly required, remove the GzipHandler from the server configuration chain.
  2. Load Balancer Filtering: Configure an upstream WAF or Load Balancer to strip Content-Encoding: gzip headers from incoming requests, effectively disabling request inflation logic before it reaches Jetty. Note that this breaks functionality for legitimate clients sending compressed data.
  3. Restart Policies: In containerized environments, configure aggressive health checks and restart policies to handle OOM crashes gracefully, though this does not prevent the DoS condition itself.

Official Patches

Eclipse JettyCommit a9e16433 fixing the GzipHandler memory leak
GitHub AdvisoryOfficial Advisory GHSA-xxh7-fcf3-rj7f

Fix Analysis (1)

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
EPSS Probability
0.04%
Top 88% most exploited

Affected Systems

Eclipse Jetty 12.0.0 through 12.0.31Eclipse Jetty 12.1.0 through 12.1.5

Affected Versions Detail

Product
Affected Versions
Fixed Version
Eclipse Jetty
Eclipse Foundation
12.0.0 - 12.0.3112.0.32
Eclipse Jetty
Eclipse Foundation
12.1.0 - 12.1.512.1.6
AttributeDetail
CWE IDCWE-400 / CWE-401
CVSS Score7.5 (High)
VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Attack VectorNetwork (Remote)
Exploit MaturityPoC Available
EPSS Score0.04%

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
T1499.003Application Exhaustion
Impact
CWE-400
Uncontrolled Resource Consumption

Uncontrolled Resource Consumption

Known Exploits & Detection

Manual AnalysisExploitable by sending compressed requests without accept-encoding header

Vulnerability Timeline

Fix committed to repository
2025-12-29
Advisory published
2026-03-05

References & Sources

  • [1]GHSA-xxh7-fcf3-rj7f: Native Memory Leak in GzipHandler
  • [2]NVD CVE-2026-1605

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.