In late March 2022, a proof-of-concept exploit briefly surfaced on GitHub before its author pulled it down — but not before screenshots and mirrors had already spread across security Twitter. What it revealed was a critical, unauthenticated remote code execution flaw in the Spring Framework, the dependency injection and web MVC backbone underneath a huge share of enterprise Java applications. The vulnerability, tracked as CVE-2022-22965 and nicknamed "Spring4Shell" in an echo of the Log4Shell panic just four months earlier, let an attacker send a single crafted HTTP request and walk away with a web shell on the server. No authentication, no user interaction, no social engineering — just a POST request against the right combination of components. Within days, mass internet scanning and active exploitation attempts were observed, and CISA added it to the Known Exploited Vulnerabilities catalog. For any organization running Java in production, Spring4Shell was a five-alarm fire, and understanding exactly which applications were actually exposed — versus merely using Spring somewhere in the stack — became the defining challenge of the response.
What Spring4Shell actually is
Spring4Shell exploits the Spring Framework's data-binding functionality — the mechanism that automatically maps incoming HTTP request parameters onto Java object properties. Under the right conditions, an attacker can supply parameter names that reach through an object's getter chain into class.module.classLoader, giving them a path to manipulate the application's class loader. On a server running Apache Tomcat, this can be abused to write a malicious JSP file directly into the webroot, which the attacker then requests to execute arbitrary code.
This is not a brand-new bug pattern. It is a close cousin of CVE-2010-1622, a Spring data-binding vulnerability disclosed over a decade earlier. That older issue was mitigated in later JDK versions because the class loader property chain wasn't reachable through the exposed getters. JDK 9's introduction of the module system reintroduced a reachable path via getClass().getModule(), effectively resurrecting the old vulnerability class under new plumbing. It's a textbook example of how a fix that quietly depended on runtime internals can silently regress when the runtime changes underneath it — years after everyone stopped thinking about the original bug.
Affected versions and components
For Spring4Shell to be exploitable, several conditions generally need to align:
- Spring Framework versions: 5.3.0 through 5.3.17, 5.2.0 through 5.2.19, and older unsupported branches. Spring Boot applications inherit this exposure through their Spring Framework dependency.
- JDK 9 or later: The vulnerable code path depends on class loader access patterns introduced by the Java Platform Module System.
- Apache Tomcat as the servlet container, with the application packaged and deployed as a WAR file (rather than an embedded, executable JAR) — this is what makes the JSP webshell write technique work in the most commonly described exploitation path.
- Spring-webmvc or spring-webflux on the classpath, since data binding is central to how these modules process request parameters.
Applications packaged as self-contained executable JARs with embedded Tomcat are generally less exposed to the specific WAR-based exploitation technique, but Spring/VMware and multiple researchers cautioned that other exploitation vectors were plausible depending on application structure, custom controllers, and how data binding was configured. Treating "not a WAR on Tomcat" as a full pass was, and remains, risky. The safest posture was — and is — to patch regardless of deployment packaging.
It's also worth separating Spring4Shell from a second, unrelated vulnerability disclosed the same week: CVE-2022-22963, a Spring Cloud Function SpEL injection bug. The two landed almost simultaneously, generated overlapping headlines, and caused real confusion in vendor advisories and patch tracking. Security teams triaging both at once needed to be precise about which CVE applied to which service, since the affected components, exploitation mechanics, and fixes are entirely distinct.
CVSS, EPSS, and KEV context
CVE-2022-22965 was scored 9.8 (Critical) on CVSS v3.1 — reflecting network-exploitability, no privileges required, no user interaction, and a complete impact on confidentiality, integrity, and availability once a web shell is dropped. Given the pre-patch public POC leak, unauthenticated RCE, and the sheer footprint of Spring in enterprise Java, EPSS (Exploit Prediction Scoring System) probabilities for this CVE climbed rapidly into the high-90th-percentile range within days of disclosure — a strong signal that active, widespread exploitation was not hypothetical but already underway. CISA added Spring4Shell to its Known Exploited Vulnerabilities (KEV) catalog in April 2022, which for federal agencies under Binding Operational Directive 22-01 meant mandatory remediation on an accelerated timeline. For any organization mapping its own prioritization to KEV status, EPSS score, and CVSS severity, Spring4Shell checked every box that should trigger an emergency patch cycle rather than a routine one.
Timeline
- March 29, 2022: A researcher publishes a proof-of-concept exploit on GitHub, then deletes the repository within hours. Screenshots and forks already exist in the wild, and details begin circulating rapidly across security research channels — before an official advisory or patch exists.
- March 30, 2022: VMware/Spring confirms the vulnerability, assigns it as an unresolved data-binding RCE issue, and publishes interim mitigation guidance while a fix is finalized.
- March 31, 2022: Official patched releases ship — Spring Framework 5.3.18 and 5.2.20, alongside Spring Boot 2.5.12 and 2.6.6, which pull in the fixed framework version.
- April 1, 2022 and beyond: Mass internet-wide scanning and exploitation attempts are observed almost immediately, including botnet activity (Mirai variants) incorporating the exploit for automated compromise.
- April 2022: CISA adds CVE-2022-22965 to the KEV catalog, and multiple national CERTs issue advisories urging emergency patching.
The compressed timeline — public POC leak before an official patch existed — is what made Spring4Shell especially dangerous. Defenders had to lean on interim mitigations for roughly 48 hours before an authoritative fix was available, all while exploitation was already ramping up.
Remediation steps
- Upgrade Spring Framework to 5.3.18 or later (5.3.x line) or 5.2.20 or later (5.2.x line). If you're on an older, unsupported Spring branch, plan a broader upgrade — those versions won't receive a targeted fix.
- Upgrade Spring Boot to 2.5.12 or later, or 2.6.6 or later, which transitively pull in the patched Spring Framework version. Verify your dependency tree; a Spring Boot bump alone doesn't help if a build override pins an older Spring Framework artifact.
- If immediate patching isn't possible, apply the interim mitigation: register a global
ControllerAdvicewith anInitBinderthat addsclass.*,Class.*,*.class.*, and*.Class.*to theWebDataBinder's disallowed fields. This blocks the property-path pattern the exploit relies on without requiring a framework upgrade. - Patch or upgrade Apache Tomcat to a version that closes the related class loader manipulation path (9.0.62, 8.5.78, or 10.0.20 and later). Tomcat's own fix independently blocks the most common WAR-based exploitation technique, providing defense in depth even after the Spring-side patch is applied.
- Add WAF/IPS detection rules for request parameters containing
class.module.classLoader-style patterns as a stopgap and as ongoing detection for exploitation attempts against systems you haven't fully inventoried yet. - Inventory every application actually using vulnerable Spring versions on JDK 9+, not just ones you remember shipping — this is where most organizations lost time in March 2022, manually walking build files and dependency trees under pressure.
How Safeguard Helps
The hardest part of responding to Spring4Shell wasn't applying the patch — it was finding every application that actually needed it, fast, without drowning in false positives from projects that merely list Spring somewhere in a transitive dependency tree. Safeguard's SBOM generation and ingest pipeline builds a live, accurate inventory of every Spring Framework and Spring Boot version running across your services, so you're not reconstructing that list from memory during an incident. Griffin AI correlates that inventory against CVE-2022-22965 and its exploitation conditions — JDK version, Tomcat deployment, WAR packaging, spring-webmvc/webflux presence — and reachability analysis goes further, tracing whether the vulnerable data-binding code path is actually invoked by your application logic rather than just present on the classpath. That distinction is what separates a real emergency from noise, letting your team triage by exploitability instead of by CVE ID alone. Where a fix is available, Safeguard's auto-fix PRs open the dependency bump directly against the affected repositories, cutting the time between "patch released" and "patch deployed" from days to hours — exactly the margin that mattered most in the 48 hours between the Spring4Shell POC leak and the official fix.