- Published on
Explaining the React Server Components Security Issue
- Authors
- Name
- Rosa Tiara
What happened?
On December 3, 2025, the React team disclosed CVE-2025-55182 (React2Shell), a critical unauthenticated remote code execution (RCE) vulnerability affecting React Server Components (RSCs).
If you have a React project, check your email, you might get this warning too.
This flaw stemmed from how Next.js handled React Server Component requests, which allows remote attackers to execute arbitrary code on servers running vulnerable versions.
What was the attack?
The attack was Remote Code Execution (RCE). RCE occurs when an attacker runs malicious code on an organization's computers or network. An attacker could send a malicious request and the server would execute it as if it were trusted code. They simply send it and it is executed automatically with no login or user interaction required.
Who was the attacker?
There was no attacker. RCE usually occurs because of vulnerabilities in web applications and network infrastructure. The real cause was a flaw in React's Server Component serialization logic.
Why is it dangerous?
- The exploit does not require authentication.
- It affects default configurations of React Server Components and downstream frameworks (Next.js, etc.). That means many production applications are vulnerable just by using RSC.
- It's severe: the score is 10.0 (critical) under standard vulnerability severity ratings.
Explanation (Technical)
For a general non-technical overview, refer to the next part.
Expected flow
The client sends structured data that describes UI components. The server reads it and rebuilds the UI without executing anything from the client.
Client
|
| RSC Payload (structured data)
v
React Flight Decoder
|
| Deserializes the payload
v
RSC Runtime
|
| Builds components and attaches server actions
v
Server Execution Environment
The flow above assumes that:
- The client data is trusted
- The payload only includes allowed fields (component names, props, references)
- The data cannot influence server execution beyond rendering
What actually happened
The problem happens when the server turns the incoming data back into objects and runs it, instead of treating it as just data to read. This is problematic because data should never be able to control what the server does. When the server runs data instead of just reading it, an attacker can send specially crafted input that makes the server execute their commands. That means they can bypass security and run unintended code.
Incoming RSC Payload
|
v
Deserialization Layer
|
| Interprets certain fields as:
| - component pointers
| - server function links
| - execution instructions
v
Execution Mapping Layer
|
v
Code runs with server privileges
TL;DR The vulnerability exists because the server trusted client-controlled serialized data and treated parts of it as executable instructions. Without validation or isolation, attackers could craft payloads that trigger server-side code execution.
Explanation (Non-Technical)
In short, this is the general explanation of the attack.
Message sent by user
↓
System reads message
↓
System executes it directly
It is problematic because there was no step to check these things:
- Is this message safe?
- Is this allowed?
- Is this from a trusted source?
What part of Next.js was affected?
According to the official Next.js report, applications using React Server Components with the App Router are affected when running:
- Next.js 15.x
- Next.js 16.x
- Next.js 14.3.0-canary.77 and later canary releases
Next.js 13.x, Next.js 14.x stable, Pages Router applications, and the Edge Runtime are not affected.
Required actions
Please refer to the official Next.js documentation for the required actions. There is no other workaround except upgrading to a patched version.
Summary
Next.js found a critical security issue in how React Server Components handled incoming data. Because of this flaw, data from the client could be mistakenly treated as code and executed on the server. Attackers could abuse it to run their own commands. The fix changed how data is processed and ensured user input is never treated as executable code.
I hope this blog helps you understand it. Have a good day!