Vulnerability Management

Spring4Shell (CVE-2022-22965) Response Analysis

A 2010-era bypass resurfaced as CVE-2022-22965 on Spring Framework for JDK 9+. Here is how the disclosure, patch, and industry response actually went.

Nayan Dey
Senior Security Engineer
6 min read

On March 29, 2022, a Chinese-language researcher tweeted a screenshot of what appeared to be a remote code execution vulnerability in Spring Framework. Within 24 hours, the tweet was deleted, proof-of-concept exploits were circulating on GitHub, and every security team running Java in production was either hunting or in crisis mode. On March 31, VMware published the official advisory assigning CVE-2022-22965 with CVSS 9.8. The vulnerability was a regression of a 2010 class of bugs (CVE-2010-1622) specifically against the DataBinder mechanism when running on JDK 9 or later, exploitable when Spring MVC processed parameters that controlled nested bean properties like class.module.classLoader. A working exploit overwrote Tomcat's access log configuration to drop a JSP web shell. The disclosure happened out of sequence, the patch (Spring Framework 5.3.18 and 5.2.20) landed within 48 hours, and CISA added the CVE to the Known Exploited Vulnerabilities catalog on April 4. This post walks through what made Spring4Shell interesting and where response patterns succeeded or failed.

Why did a 2010-class bug resurface as a 2022 CVE?

A 2010-class bug resurfaced because Spring's 2010 fix for CVE-2010-1622 blocked the specific class.classLoader attack path against Java 8 and earlier, but JDK 9 introduced the Java Platform Module System, which added the class.module property to java.lang.Class. That new property created a new traversal path — class.module.classLoader — that the original fix did not anticipate. The vulnerability existed from JDK 9's release (September 2017) onward, latent in every Spring MVC application that used @RequestMapping handlers with POJO binding. Practically, that is the majority of Spring MVC applications. Exploitation required the application to deploy as a traditional WAR on a servlet container (Tomcat was the common case) — standalone Spring Boot JARs were not exploitable via the same primitive because their embedded Tomcat did not expose the log-configuration sink. The nuance mattered: many teams read "Spring RCE" and panicked over Spring Boot apps that were not actually vulnerable.

How did exploitation actually work?

Exploitation worked by sending a specially crafted POST request that manipulated Tomcat's access log valve configuration through DataBinder property traversal, writing a JSP webshell to a path inside the web root. The canonical proof-of-concept request included parameters like:

class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di
class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp
class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT
class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar
class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=

Combined with a subsequent request whose URL contained the payload string, the logging valve would write that string verbatim to webapps/ROOT/tomcatwar.jsp, creating an attacker-controlled JSP. Requesting tomcatwar.jsp?cmd=id then executed arbitrary commands. Spring's fix restricted the DataBinder to exclude the class property path entirely.

Why was the disclosure timeline so chaotic?

The disclosure timeline was chaotic because proof-of-concept code leaked on GitHub and Chinese social media before VMware had finalized a patch. The researcher who tweeted the screenshot deleted it, but archival captures spread within minutes. A forked PoC repository reached 1,000 stars in under six hours. By the time VMware published the official advisory, the commercial threat intelligence community had already confirmed in-the-wild exploitation attempts, with Akamai reporting 37,000 exploit attempts in the first 24 hours. This is the modern disclosure reality: once a credible visual of an RCE lands on public social media, the embargo is effectively over, and the vendor is racing the attackers to ship a patch. Spring Framework's maintainers moved fast — 48 hours from leak to patched release is excellent by any measure — but the window still saw real exploitation.

What made the response difficult for operators?

The response was difficult because identifying vulnerable instances required more than a version check. The vulnerability depended on the combination of: Spring Framework < 5.3.18 or < 5.2.20, JDK 9+, deployment as a traditional WAR (not Spring Boot fat JAR), running on a servlet container, and using @RequestMapping with POJO data binding. SCA tools flagged every Spring-using application as potentially vulnerable, which was technically defensible but operationally useless for prioritization. Teams spent days triaging thousands of false positives. The correct scoping query — packaged as a WAR, bound-POJO request handler exposed on a reachable endpoint — required source-level analysis that most SCA products did not offer. This is precisely the gap that reachability analysis closes: the tool needs to answer "is the vulnerable code path live in this deployment?" rather than "is the vulnerable library present?"

What were the real-world exploitation outcomes?

The real-world exploitation outcomes included early Mirai-variant botnets incorporating Spring4Shell probes, cryptominer deployments against exposed enterprise apps, and at least one confirmed ransomware precursor access documented by Trend Micro in April 2022. CISA's KEV catalog addition on April 4 triggered mandatory patching for federal agencies within two weeks under Binding Operational Directive 22-01. By mid-April, Shodan and Censys scans of internet-exposed Spring MVC instances showed patch rates climbing from ~15% to ~70%, which is aggressive for a CVE of this class but still left the long tail of forgotten vendor appliances exposed for months. The long tail is always where the next ransomware case study comes from, and Spring4Shell contributed victims through 2022 and into 2023.

What is the durable lesson for vulnerability management?

The durable lesson is that a package-level CVE is not equivalent to a deployment-level vulnerability, and treating them as equivalent produces response paralysis. Effective response requires a reachability model: what libraries are loaded, what entry points are exposed, what runtime conditions (JDK version, packaging format, enabled handlers) activate the vulnerable code path. Teams that had this model in 2022 could respond to Spring4Shell in hours with a precise, short list of assets. Teams without it spent a week triaging. The industry has improved here — SBOM adoption, VEX documents, and runtime context correlation are all more common in 2024 than in 2022 — but the fundamental discipline is: separate library presence from deployment-reachable vulnerability. Do the analysis once, for your critical stacks, and keep it current.

# Example reachability query post-Spring4Shell
# Is the vulnerable DataBinder path invoked by any exposed handler?
grep -rE '@RequestMapping|@PostMapping' src/main/java | \
  xargs -I {} grep -l 'BeanUtilsBean\|DataBinder' {}
# Is JDK 9+? Is packaging WAR?
javac -version; grep -E 'packaging>war' pom.xml

That is the manual equivalent of what modern reachability tooling does automatically across a portfolio of services.

How Safeguard Helps

Safeguard's reachability analysis tells you whether Spring4Shell-class advisories actually apply to a specific service — JDK version, packaging format, handler exposure, and the precise bean-binding path — so your triage list is a handful of services rather than your entire Java estate. Griffin AI drafts patch rollout plans, tests required deployment surface for the CVE condition, and generates executive summaries during the chaos of a zero-day like this one. SBOM ingestion correlates the full Spring transitive tree against the NVD and VMware advisories in real time. TPRM surfaces which of your vendors embed vulnerable Spring versions so you can open tickets with them immediately. Policy gates block releases that ship a KEV-listed vulnerable Spring version without an applied mitigation or compensating control.

Never miss an update

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