Safeguard
AppSec

Spring Framework RCE Vulnerabilities: A History

From Spring4Shell to older data binding flaws, Spring framework RCE bugs keep resurfacing in the same handful of places — data binding, expression evaluation, and class loading.

Safeguard Research Team
Research
6 min read

Spring framework RCE vulnerabilities have surfaced repeatedly over the framework's history, and while each one has its own CVE and its own specific trigger, most trace back to one of three recurring mechanisms: overly permissive data binding, expression language evaluation of untrusted input, and class loading tricks that reach dangerous objects through the Java class loader. Because Spring underpins a huge share of enterprise Java applications, a single spring RCE bug tends to have an outsized blast radius, which is exactly why the framework's maintainers and the broader Java security community treat these disclosures as high priority.

What was Spring4Shell and why did it matter so much?

Spring4Shell, tracked as CVE-2022-22965, was disclosed in early 2022 and became one of the most widely discussed Spring vulnerabilities in recent years — partly because of its severity and partly because of the name's deliberate echo of Log4Shell, which had rattled the industry just months earlier. The bug exploited Spring's data binding feature, specifically how the framework binds HTTP request parameters to Java object properties. Under the right conditions — running on Java 9 or later, deployed as a WAR on Apache Tomcat, using Spring's parameter binding to a POJO — an attacker could manipulate the class loader through crafted parameter names, ultimately writing a malicious file to the server and achieving remote code execution.

The practical fix involved patching the vulnerable Spring versions and, notably, applying restrictions to which fields data binding is allowed to touch — essentially denylisting access to internal class loader-related properties by default. It underscored a pattern that shows up across most spring rce history: features designed for developer convenience (automatically mapping request data onto objects) become the attack surface when they're too permissive about which properties they'll touch.

How does Spring Expression Language contribute to RCE bugs?

Spring Expression Language, commonly abbreviated SpEL, is a powerful expression language embedded throughout the Spring ecosystem for things like configuring bean properties and evaluating conditional logic in annotations. The danger is that SpEL expressions can invoke arbitrary Java methods, and several Spring RCE vulnerabilities over the years have stemmed from user-controllable input reaching a SpEL evaluation context. If an attacker can inject their own expression into a field that later gets evaluated as SpEL, they can potentially call Runtime.exec or equivalent methods and execute arbitrary commands on the server.

This pattern isn't unique to Spring — it's the same fundamental risk as any embedded expression or template language (Java's broader ecosystem has seen similar issues in OGNL-based frameworks) — but Spring's pervasive use of SpEL across its configuration and annotation-processing internals has made it a recurring theme across the platform's vulnerability history rather than an isolated incident.

What role does data binding play across these bugs?

Beyond Spring4Shell specifically, Spring's data binding mechanism — the same feature that makes it convenient to accept a form submission and automatically populate a Java object — has been a repeat offender because binding by default is permissive: unless explicitly restricted, it will attempt to set any property on the target object that matches an incoming parameter name, including nested properties reached through getter/setter chains. That flexibility is what allowed the Spring4Shell class-loader manipulation to work in the first place, and it's why Spring's own security guidance has increasingly pushed toward allowlisting bindable fields rather than relying on the framework's defaults.

How should teams stay ahead of Spring RCE risk?

Patch discipline matters more here than almost anywhere else, since Spring vulnerabilities are disclosed publicly with enough technical detail that working exploits typically appear within days, sometimes hours. Tracking exactly which Spring, Spring Boot, and Spring Security versions are running across every service — including transitive pulls through other libraries that bundle a Spring dependency — is a dependency inventory problem at scale, which is precisely what software composition analysis exists to solve; knowing you're running a vulnerable spring-security-oauth2 or spring-core version buried three layers deep in a transitive dependency tree is not something most teams can track by hand across dozens of services.

Beyond patching, a few structural habits reduce exposure to the next Spring RCE before it's even disclosed: avoid binding untrusted request data directly to complex object graphs where possible, prefer dedicated DTOs with only the fields you actually need over binding straight to domain objects, and treat any place where user input might reach a SpEL evaluation context as a code review priority. Static analysis that specifically flags user-controlled input flowing into expression evaluation or reflection-heavy APIs, as part of a broader SAST/DAST pipeline, catches a meaningful share of these patterns before they ship, even when the specific CVE hasn't been disclosed yet.

FAQ

Is Spring4Shell the same as Log4Shell?

No, though the names are intentionally similar and both surfaced around the same period. Log4Shell (CVE-2021-44228) was a vulnerability in the Log4j logging library's JNDI lookup feature; Spring4Shell (CVE-2022-22965) was a separate vulnerability in Spring's data binding and class loader handling. They're unrelated codebases affected by conceptually similar "user input reaches a dangerous feature" root causes.

Which Spring versions were affected by Spring4Shell?

Spring Framework versions 5.3.0 through 5.3.17 and 5.2.0 through 5.2.19 were vulnerable, specifically when running on Java 9 or later and deployed as a traditional WAR file on a servlet container like Tomcat. Spring Boot applications packaged as executable JARs with an embedded servlet container were generally not exposed to the exact exploitation path, though patching still applied broadly across the ecosystem.

Are Spring RCE vulnerabilities specific to Spring Boot or the broader Spring Framework?

Both have had vulnerabilities, since Spring Boot is built on top of the core Spring Framework and inherits its data binding and SpEL machinery. Some CVEs are scoped to specific modules like Spring Security OAuth2, while others affect core Spring Framework classes used regardless of which Spring project you're using.

How quickly are Spring RCE vulnerabilities typically exploited after disclosure?

Given Spring's ubiquity in enterprise Java applications, working proof-of-concept exploits for major Spring RCE disclosures have historically appeared within days of public disclosure, sometimes faster once technical details or a diff between patched and vulnerable versions circulates. That compressed timeline is a strong argument for automated dependency alerting rather than manual changelog tracking.

Never miss an update

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