Vulnerability Management

Apache Tomcat CVE-2025-24813: a deserialization deep dive

Tomcat's partial-PUT deserialization RCE turned a session persistence feature into a remote code execution path, and the pattern is one Java middleware keeps repeating.

Hritik Sharma
Staff Engineer
7 min read

Apache Tomcat CVE-2025-24813, disclosed in March 2025, is the kind of vulnerability that makes Java middleware operators sigh because it is a familiar class of bug in a new wrapper. The advisory describes a remote code execution path that requires several specific configuration conditions to be present simultaneously: the Tomcat default servlet must have read-write enabled, partial PUTs must be permitted, the application must use Tomcat's file-backed session persistence with a known and predictable session ID, and the application must include a library on its classpath that the attacker can chain through Java deserialization. The conjunction sounds narrow until you remember how many shops run Tomcat with stale configuration, how often the default servlet's write capability gets enabled for legitimate file upload features, and how common Commons Collections or similar gadget-rich libraries are on a Java classpath.

The mechanism is that an attacker uploads, via partial PUT, a serialized Java object as the contents of what Tomcat believes is a session file in its file-backed session store. When Tomcat later loads a session whose ID matches the attacker-supplied filename, it deserializes the contents using ObjectInputStream and the gadget chain executes whatever it was crafted to execute. The patch landed in Tomcat 9.0.99, 10.1.35, and 11.0.3, and the recommended posture is to disable partial PUT support unless an application explicitly requires it, but the broader lesson is about why deserialization keeps producing CVEs in 2025 when the unsafe pattern has been understood since at least 2015.

How does the exploit chain actually work?

The Tomcat default servlet, when read-write is enabled, accepts PUT requests for file uploads. Partial PUT is a feature where a client sends a Content-Range header indicating that the request body is a fragment of a larger file, and the server stores the fragment in a temporary location while it waits for the rest. CVE-2025-24813's first ingredient is that the temporary storage path for partial PUTs can be made to overlap with the file-backed session storage path under certain configurations, especially when the work directory and the session storage directory are aligned with their defaults.

The second ingredient is that Tomcat's file-backed session persistence reads session state by file name. If an attacker can write a file with a name that matches the SHA-1 session ID format, and if they can put serialized Java content in that file, Tomcat will deserialize it the next time it tries to load that session. The third ingredient is the deserialization gadget chain, which is where Commons Collections, Spring, Groovy, or similar libraries come into play. Tomcat itself does not provide a gadget; it provides the deserialization sink, and the gadget comes from whatever the application happens to have on its classpath. The conjunction of the three conditions is what makes the vulnerability work, and the Tomcat security team's writeup is careful to note that any single mitigation breaks the chain.

What changed in patch 9.0.99, 10.1.35, and 11.0.3?

The Tomcat patch hardens the partial PUT path so that the temporary storage cannot be coerced into the session storage namespace, and adds a configuration option to disable partial PUT entirely. The session loader was also tightened to reject files whose contents do not match the expected serialized-session header, which is defense-in-depth against any future overlap. The upstream guidance is to apply the patch and, separately, to disable partial PUTs unless the application requires them, which most do not.

The operational reality of patching is the usual Tomcat story. Enterprise Java estates pin Tomcat versions per application, run several major versions in parallel, and rely on application-team-driven rebuilds to push the patch out. The patch curve is therefore a function of application team velocity rather than a single platform decision, and CVE-2025-24813 was still showing up in supply chain scans of production deployments well into late 2025. The Tomcat container image ecosystem made this worse for a stretch because some popular base images shipped pre-9.0.99 Tomcat builds for several weeks after disclosure, propagating the vulnerable code into newly built images.

Why does Java deserialization keep producing CVEs?

The unsafe-deserialization pattern in Java has been understood since the FoxGlove Security writeup in 2015, and the recommended defense, which is to never deserialize untrusted input with ObjectInputStream without a strict allowlist, is well known. The reason CVEs keep appearing is structural. Java deserialization is woven through the standard library and through frameworks in ways that are not always visible to application authors, with session persistence, JNDI, RMI, JMX, and various caching and replication features all using ObjectInputStream under the hood. Removing the pattern requires either eliminating those features or wrapping every ObjectInputStream with a filter, and Java only added the ObjectInputFilter API in JDK 9 with broader adoption in JDK 17.

The gadget supply side is the other half of the problem. Commons Collections, Spring, Groovy, Hibernate, and various other libraries contain classes whose internal logic can be chained into arbitrary code execution when fed a crafted serialized object. The libraries are not vulnerable in their normal use, but their presence on a classpath turns any deserialization sink elsewhere into an exploit. The supply chain answer is to track which classpath libraries contain known gadget chains and to treat their presence as elevating the severity of any unrelated deserialization sink. CVE-2025-24813 was severe because Commons Collections is on most Tomcat application classpaths; it would have been a different conversation in a stripped-down environment.

What should middleware operators change in 2026?

The first change is to inventory deserialization sinks and gadget libraries together. An SBOM that lists Commons Collections without also flagging the Tomcat session loader, the Spring deserializing endpoints, or the JMX surface is incomplete from a deserialization-risk perspective. Tooling that joins those two facts and produces a single "reachable deserialization sink with gadgets on path" finding gives operators a prioritization signal that severity alone does not.

The second change is to set Tomcat configuration defaults that close the partial-PUT and file-backed-session attack surface for applications that do not need them. The default servlet's read-write capability, partial PUT support, and file-backed session persistence are all features that the typical web application does not use, and the operational discipline of disabling them by default would have closed CVE-2025-24813 for most affected sites. The third change is to migrate session persistence away from file-backed Java serialization toward a typed serialization format like JSON or protobuf where the deserialization is bounded by a schema, which removes the gadget-chain exploit class entirely. The fourth change is to enable Java's ObjectInputFilter globally, with an allowlist that explicitly excludes Commons Collections and similar gadget-rich packages.

How Safeguard Helps

Safeguard ingests SBOMs from Tomcat application builds and base images, identifying Tomcat versions vulnerable to CVE-2025-24813 alongside the gadget libraries on the same classpath, so that a finding is prioritized by the conjunction of sink and gadget rather than by sink alone. Griffin AI's reachability analysis evaluates whether the partial-PUT and file-backed-session features are reachable in the application's actual configuration, distinguishing pre-9.0.99 Tomcat deployments that have those features disabled from those that have them on. Policy gates can block deployment of container images that ship vulnerable Tomcat builds with Commons Collections on the classpath, and the TPRM workflow flags upstream vendors whose Java middleware products embed unpatched Tomcat versions. The remediation guidance generated for affected projects includes both the version upgrade path and the configuration changes that close the attack surface where patching is delayed.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.