In April 2020, Apache Tomcat patched CVE-2020-9484, a deserialization vulnerability in the PersistenceManager session-persistence mechanism that could lead to remote code execution. Less than a year later, the Tomcat security team disclosed CVE-2021-25329: the original fix was incomplete. Under a narrow but real non-default configuration, an attacker who could already control the name and partial contents of a file on the server's filesystem could still trigger deserialization of that file through session ID manipulation — the exact class of bug CVE-2020-9484 was supposed to have closed off. For organizations that patched in 2020 and considered the issue resolved, CVE-2021-25329 was a reminder that "we already fixed this" is not the same as "this is fixed."
What went wrong
Tomcat's PersistenceManager can be configured with a FileStore to persist HTTP session objects to disk between restarts or across a cluster. The original vulnerability, CVE-2020-9484, existed because Tomcat would deserialize a file from the session storage directory based on a session ID supplied by the client. If an attacker could separately upload or place a file with attacker-controlled content at a predictable path, and knew (or guessed) the relative path from the storage location, they could coerce Tomcat into deserializing that file — and a malicious serialized Java object graph can equal remote code execution.
The 2020 patch tightened the session ID validation and file-path handling used by PersistenceManager/FileStore to prevent this path traversal and deserialization trigger. CVE-2021-25329 exists because that tightening didn't cover every code path. Specifically, when Tomcat was configured with session persistence in a way that fell outside the primary scenario the 2020 fix addressed, the same deserialization trigger was still reachable. Apache's own advisory language is notably candid about this: the fix for CVE-2020-9484 was "found to be incomplete" for what the project describes as a highly unlikely non-default configuration edge case — not a total bypass of the earlier patch, but a gap left in it.
This pattern — an initial fix that narrows a vulnerability's exploitability without eliminating its root cause — is common in real-world vulnerability remediation, and it is exactly why supply chain and dependency-monitoring teams shouldn't treat a patched CVE as a permanently closed chapter for that component.
Affected versions and components
CVE-2021-25329 affects Apache Tomcat's session persistence subsystem (org.apache.catalina.session.PersistenceManager used together with FileStore) across the following version ranges, consistent with Apache's published advisory:
- Apache Tomcat 10.0.0-M1 through 10.0.0
- Apache Tomcat 9.0.0.M1 through 9.0.41
- Apache Tomcat 8.5.0 through 8.5.61
- Apache Tomcat 7.0.0 through 7.0.107
Exploitability depends on a specific, non-default deployment configuration involving session persistence to a FileStore combined with an attacker's ability to place or influence files on the server's filesystem at a location reachable from the configured storage path. Deployments that do not use PersistenceManager/FileStore, or that use it only in Tomcat's default configuration, are not affected by this particular gap. As with the original CVE-2020-9484, the practical risk is concentrated in multi-tenant or shared hosting environments, and in applications that allow file upload or file write primitives elsewhere in the stack — conditions that turn a theoretical deserialization gadget into a real remote code execution chain.
CVSS, EPSS, and KEV context
Apache classifies the issue consistent with the severity of the original CVE-2020-9484 finding, given that a successful exploit chain results in remote code execution on the server. Because exploitation requires a non-default configuration plus an independent file-write or file-placement primitive, real-world exploitability is lower than a "wormable, pre-auth RCE" headline would suggest — the vulnerability is best understood as a second-stage or chained primitive rather than a standalone internet-facing exploit path. We are not aware of CVE-2021-25329 being listed on CISA's Known Exploited Vulnerabilities (KEV) catalog, and we have not seen credible reports of widespread in-the-wild exploitation specific to this incomplete-fix variant, as opposed to the broader awareness that followed the original 2020 disclosure. Teams tracking exposure should still pull current CVSS and EPSS values from NVD and FIRST.org at scan time rather than relying on point-in-time figures, since EPSS scores in particular are recalculated regularly as exploitation intelligence evolves.
Timeline
- 2020: Apache Tomcat discloses and patches CVE-2020-9484, a
PersistenceManager/FileStoredeserialization vulnerability, hardening session ID handling and file-path resolution to prevent triggered deserialization of attacker-influenced files. - Early 2021: Further review of the session-persistence code path identifies that the 2020 remediation did not close every route to the same deserialization trigger under a specific non-default configuration.
- 2021: Apache publishes CVE-2021-25329 alongside fixed releases across the 7.0.x, 8.5.x, 9.0.x, and 10.0.x branches, along with an advisory explicitly noting that this CVE addresses the incompleteness of the earlier fix.
- Ongoing: The CVE remains a useful case study cited in Tomcat hardening guidance and in discussions of Java deserialization risk more broadly, since it illustrates how session-persistence features are a recurring soft spot even after a documented remediation.
Because Apache's advisories for both CVEs are the authoritative source for exact patch and release dates, teams doing compliance attestation or audit documentation should cite the official Tomcat security page rather than secondary summaries.
Remediation steps
- Upgrade to a fixed Tomcat release. Apache's security advisory identifies patched builds in each of the 7.0.x, 8.5.x, 9.0.x, and 10.0.x branches that resolve both CVE-2020-9484 and CVE-2021-25329. Confirm your exact deployed version against Apache's current security advisory page before and after upgrading, since branch-specific fixed versions should always be verified against the live advisory rather than a cached list.
- Audit
PersistenceManager/FileStoreconfiguration. If yourcontext.xmlorserver.xmlconfigures session persistence to disk, review whether it uses any non-default settings and confirm the deployment matches Apache's guidance for safe configuration post-patch. - Eliminate the file-write precondition where possible. Because exploitation requires an attacker to influence file names or contents on the server filesystem, review adjacent attack surface — file upload handlers, log injection points, shared storage misconfigurations — that could hand an attacker this primitive even if Tomcat itself is patched.
- Restrict filesystem and directory permissions around the session storage path so that only the Tomcat process, not application code or co-tenants, can write to it.
- Inventory every Tomcat instance across your environment. This CVE is a strong example of why a single "we patched Tomcat" checkbox isn't enough — incomplete fixes mean the same CVE ID can require a second remediation pass. Confirm build-level version data, not just "patched" status, for every service, container base image, and embedded Tomcat instance (including those bundled inside other Apache Java projects).
- Track downstream and vendored copies. Tomcat is frequently embedded inside other products; verify that vendor-supplied builds and container images have propagated the fix, not just your directly managed servers.
How Safeguard Helps
CVE-2021-25329 is a textbook argument for continuous, build-accurate software composition analysis rather than a one-time patch checklist. Safeguard's platform is built for exactly this scenario:
- Precise version and build fingerprinting across your software supply chain means Safeguard can distinguish a Tomcat instance running a version vulnerable to CVE-2020-9484 alone, one still exposed to the incomplete-fix follow-up in CVE-2021-25329, and one running a fully patched build — rather than treating "Tomcat, patched" as a single undifferentiated state.
- Continuous re-scanning catches exactly this failure mode: a CVE that gets a second advisory after the first fix turns out to be incomplete. Safeguard doesn't assume a component is permanently clear once a CVE ID has been marked "remediated" — it keeps evaluating new advisories against your actual deployed inventory.
- Configuration-aware risk context helps teams prioritize realistically. Because this vulnerability's exploitability hinges on non-default
PersistenceManager/FileStoreconfiguration plus a chained file-write primitive, Safeguard's findings are presented with the deployment context needed to triage accurately instead of treating every affected version as equally urgent. - Software Bill of Materials (SBOM) visibility extends coverage to Tomcat instances embedded inside third-party and vendor products, not just servers your team provisioned directly — closing the blind spot where an incompletely-fixed CVE like this one lingers unnoticed in a dependency you don't directly manage.
- Audit-ready evidence gives security and compliance teams a defensible record of when each Tomcat instance was identified, assessed against both CVE-2020-9484 and CVE-2021-25329, and remediated — turning a two-part vulnerability history into a single, traceable remediation timeline.
Incomplete fixes are one of the hardest classes of vulnerability to manage precisely because they defeat the intuitive assumption that patching once is enough. Safeguard is designed to keep watching after the first patch lands, so a follow-up advisory like CVE-2021-25329 doesn't sit unnoticed in your environment.