In December 2025, security researchers disclosed one of the most critical vulnerabilities ever discovered in the React ecosystem: CVE-2025–55182, commonly known as React2Shell.

With a CVSS score of 10.0, this vulnerability allows unauthenticated remote code execution (RCE) through a single crafted HTTP request, affecting applications that use React Server Components (RSC) — most notably Next.js.

🔥 Quick Summary

  • Vulnerability Name: React2Shell
  • CVE: CVE-2025–55182
  • Severity: Critical (CVSS 10.0)
  • Impact: Unauthenticated Remote Code Execution
  • Affected React Versions:
  • 19.0.0
  • 19.1.0
  • 19.1.1
  • 19.2.0
  • Affected Packages:
  • react-server-dom-webpack
  • react-server-dom-parcel
  • react-server-dom-turbopack
  • Fixed Versions:
  • 19.0.1
  • 19.1.2
  • 19.2.1

Understanding React Server Components and the Flight Protocol

1️⃣ What are React Server Components?

React Server Components mean some React code runs on the server, not in the user's browser.

  • The server does the heavy work
  • The browser only gets the final result
  • This makes websites faster and lighter

2️⃣ How do the browser and server talk?

They talk using a special system called React Flight. Think of React Flight like a delivery format:

  • The browser sends a request
  • The server reads it, runs code, and sends back results

3️⃣ What are Server Actions?

A Server Action is a function that:

  • Runs only on the server
  • Can be triggered by the browser (for example, when you submit a form)

To call a Server Action, the browser sends serialized data (data turned into a special text format).

4️⃣ How does React Flight represent data?

React Flight uses special symbols (markers) to describe data types:

  • $@ → points to a chunk of data
  • $B → points to a Blob (file-like data)
  • $1:constructor:constructor → walks through object properties step by step

You can think of this like directions telling the server:

"Go here, then access this property, then that one"

5️⃣ Where is the security problem?

🚨 The vulnerability is here

The server trusts these directions too much.

  • It follows the property paths sent by the client
  • It does not properly check if those properties are safe or allowed
  • An attacker can craft malicious paths like constructor:constructor

This can allow access to dangerous internal JavaScript objects, potentially leading to remote code execution (RCE).

Serialization:

👉 Turning data or objects into a sendable format (like text or JSON).

Deserialization:

👉 Turning that received text back into objects.

The Core Vulnerability: Unsafe Deserialization

None

What kind of bug is this?

CVE-2025–55182 is an unsafe deserialization bug.

That means:

  • The server receives data from the client
  • It trusts that data too much
  • It turns it back into JavaScript objects without proper checks

2️⃣ Where is the bug in the code?

This is the dangerous part:

return moduleExports[metadata[2]];

What's happening here:

  • metadata[2] comes from the client
  • The server uses it to access a property on a module
  • No validation is done

3️⃣ Why is bracket notation dangerous?

In JavaScript, when you do:

obj["something"]

JavaScript doesn't stop at just the object itself.

➡️ It also checks:

  • the object's prototype (A hidden object that other objects inherit properties and functions from)
  • the prototype's prototype (JavaScript keeps looking up parent objects to find properties)
  • and so on (this is called the prototype chain)

So attackers aren't limited to "normal" properties.

4️⃣ The key JavaScript trick attackers abuse

Every JavaScript function has a hidden door called:

constructor

If an attacker reaches:

someFunction.constructor

They get the Function constructor.

And the Function constructor can do this:

Function("malicious code")()

💥 That means run any JavaScript code on the server.

5️⃣ How does React Flight help the attacker?

React Flight lets the client send property paths, like directions:

$1:constructor:constructor

This tells the server:

  1. Load module/chunk 1
  2. Go to its .constructor
  3. Go to .constructor again

React blindly follows these steps.

6️⃣ Why this becomes Remote Code Execution

Because:

  • The client controls metadata[2]
  • React does not limit which properties can be accessed
  • Prototype properties like constructor are reachable
  • The Function constructor can execute strings

➡️ An attacker can run arbitrary code on the server

The Exploitation Chain: From Deserialization to Remote Code Execution

Now let's dissect how maple3142's proof-of-concept achieves remote code execution.

Big picture

There is a bug in how React handles incoming data. The attacker sends fake data that looks like something React expects, but it secretly contains instructions that make the server run system commands.

This attack turns:

"I can control some data"

into

"I can run commands on the server"

Stage 1: Creating a fake object that tricks React

The attacker sends a request with a fake object that pretends to be a normal React internal object (called a Chunk).

Why this matters:

  • React expects this object to behave in a certain way
  • The attacker copies that structure just enough to fool React

Key trick:

  • The object says: "When you wait for me, call my then function"
  • But that then function actually points back to React's own internal function

👉 Result:

When React processes this object, it accidentally calls its own code using attacker-controlled data.

None
Exploit Code

Stage 2: Abusing how React reads uploaded data (Blob handling)

React has special handling for Blob data (file-like data). When React sees something starting with $B, it:

  1. Treats it as a Blob
  2. Calls an internal function to read it

That internal function does something like:

response._formData.get(response._prefix + id)

The clever part (the exploit)

The attacker:

  • Replaces _formData.get with JavaScript's Function constructor
  • Controls _prefix, which contains malicious JavaScript code

So instead of:

get("normal_string")

It becomes:

Function("attacker_code_here")

⚠️ And Function() executes the code it receives

👉 Result:

React unknowingly creates and runs attacker-supplied JavaScript.

Stage 3: Running system commands (RCE)

Now that arbitrary JavaScript runs on the server, the attacker uses Node.js features to run OS commands.

Example payload:

None

What this does:

  • Accesses Node.js internals
  • Loads the child_process module
  • Runs a system command (xcalc = calculator)

This proves:

✅ The attacker can execute commands on the server

Why this is dangerous

Once code execution is achieved, the attacker can:

  • Open a reverse shell
  • Steal secrets (API keys, tokens, env variables)
  • Read or delete files
  • Pivot deeper into the system

Basically:

Whatever the Node.js process is allowed to do — the attacker can do too

One-line summary

By sending fake React objects, the attacker tricks React into calling JavaScript's Function constructor, which executes attacker-controlled code and leads to full remote code execution.

Final Flowchart

Request arrives
     ↓
React sees Server Action
     ↓
Deserialize Field0
     ↓
Field1 ($@0) → points backto Field0
     ↓
Circularobject created
     ↓
Fake"then" detected
     ↓
React thinks it's a Promise
     ↓
React usesnewFunction(...)
     ↓
Attacker code runs

Vulnerable versions

This bug CVE-2025–55182 affects apps using React Server Components (RSC), including:

  • React versions 19.0.0–19.2.0
  • Next.js versions 14.3.0-canary.77 and above, all 15.x, and 16.x before fixes
  • Other frameworks using RSC like React Router (RSC mode), Waku, and Redwood SDK

Why this is dangerous

  • Default setup is vulnerable — A normal Next.js app (create-next-app) can be attacked without changing any code
  • No login needed (no authentication) — Anyone can attack it
  • Very reliable attack — Works almost every time
  • Used everywhere — Many websites use these frameworks

Attack surface (how big the risk is)

  • 39% of cloud environments have vulnerable apps (Wiz Research)
  • Over 571,000 servers use React
  • About 444,000 servers use Next.js

👉 Even if not all are vulnerable, the number of possible targets is huge.

Exploitation:

  • We can view the app's home page.
None
Vulnerable Apps Home Page
  • At the time of writing, our preferred choice is a payload that allows us to view the command execution result in the server's response, as obtained from here.
  • Send the request to the Vulnerable Apps with the help of Burp Suite Repeater.
None
  • This payload will return the command output back to us in the server's response.