CVE-2025-48989
Patch Available.
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Apache Tomcat is an open-source implementation of the Jakarta Servlet, Jakarta Pages, Jakarta Expression Language, Jakarta WebSocket, Jakarta Annotations, and Jakarta Authentication specifications. It serves Java web applications either as a standalone servlet container and HTTP server or embedded inside an application through the tomcat-embed-core artifact. Its Catalina servlet container (org.apache.tomcat:tomcat-catalina) supplies the request-processing pipeline, including Valves such as RewriteValve, along with connectors, realms, and session management.
A denial of service vulnerability (CVE-2025-48989) has been identified in the HTTP/2 implementation of Apache Tomcat, which allows unauthenticated remote attackers to exhaust server resources with the "made you reset" attack. The denial of service typically shows up as an OutOfMemoryError.
Per OWASP: The Denial of Service (DoS) attack is focused on making a resource (site, application, server) unavailable for the purpose it was designed.
This issue affects multiple versions of Apache Tomcat.
Details
Module Info
- Product: Apache Tomcat
- Affected packages:
org.apache.tomcat:tomcat-coyote,org.apache.tomcat.embed:tomcat-embed-core - Affected versions: >=9.0.0.M1 <9.0.108, >=10.1.0-M1 <10.1.44, >=11.0.0-M1 <11.0.10
- GitHub repository: https://github.com/apache/tomcat
- Published packages:
- Package manager: Maven
- Fixed in:
- OSS Apache Tomcat 9.0.108, 10.1.44, 11.0.10
- NES for Apache Tomcat v8.5.114
Vulnerability Info
This High-severity vulnerability is found in the org.apache.tomcat:tomcat-coyote and org.apache.tomcat.embed:tomcat-embed-core packages in multiple versions of Apache Tomcat. Tomcat's HTTP/2 connector protects itself against abusive clients with a per-connection overhead count. Frames that do no useful work, such as SETTINGS, PING and stream resets, increase the count, and when it passes the configured limit Tomcat closes the connection. A stream reset is meant to cost overheadResetFactor (50 by default).
That cost was only charged for resets the client sends. When a client sends a RST_STREAM frame, Http2UpgradeHandler.reset() increases the overhead count:
public void reset(int streamId, long errorCode) throws Http2Exception {
...
increaseOverheadCount(FrameType.RST, getProtocol().getOverheadResetFactor());
...
}When Tomcat itself resets a stream, because a frame from the client broke a stream-level rule, it goes through sendStreamReset(), which builds and writes the RST_STREAM frame without touching the overhead count:
void sendStreamReset(StreamStateMachine state, StreamException se) throws IOException {
...
// Write a RST frame
byte[] rstFrame = new byte[13];
...
socketWrapper.getLock().lock();
try {
if (state != null) {
boolean active = state.isActive();
state.sendReset();
if (active) {
decrementActiveRemoteStreamCount(getStream(se.getStreamId()));
}
}
socketWrapper.write(true, rstFrame, 0, rstFrame.length);
socketWrapper.flush(true);
} finally {
socketWrapper.getLock().unlock();
}
}This is the "made you reset" attack. Instead of sending resets itself, which the overhead protection catches, the attacker opens streams and sends a malformed or out-of-state frame on each one, which makes the server reset the stream. Each reset stream stops counting toward the maxConcurrentStreams limit, so the client can keep opening new streams, and because resets sent by the server add nothing to the overhead count, the connection is never closed. A single client can make Tomcat take on far more stream work than the concurrency limit allows, exhausting server memory (typically an OutOfMemoryError) and denying service to legitimate users. The same sendStreamReset() code, with no overhead charge for sent resets, is present in the Apache Tomcat 8.5.x line.
Mitigation
Only recent versions of Apache Tomcat are community-supported. The community support version will not receive any updates to address this issue. For more information, see here. Apache Tomcat versions that are no longer community-supported are End-of-Life and have no publicly available fix.
Users of the affected components should apply one of the following mitigations:
- Upgrade to a patched version of Apache Tomcat.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.
Credits
- Gal Bar Nahum from Tel Aviv University (finder)
- Anat Bremler-Barr from Tel Aviv University (finder)
- Yaniv Harel from Tel Aviv University (finder)