From React App to Shell Access: The React2Shell Vulnerability
A maximum-severity bug in React Server Components let an unauthenticated attacker run code on the server by sending one crafted request. This is how data became a command.
Open on YouTube · video loads from YouTube when you press play
On 3 December 2025 the React team announced CVE-2025-55182, nicknamed React2Shell. It carries the highest severity score (CVSS 10.0): an attacker with no account and no credentials could make a vulnerable server run code of their choice by sending a single HTTP request.
Background: Server Components and the Flight protocol
React Server Components (RSC) run part of your React app on the server. The server and the browser exchange data using a wire format called Flight. It can carry more than plain JSON: references to other chunks, promises and, importantly, Server Functions, server-side functions your client code can call.
Frameworks that use RSC, including the Next.js App Router, expose an HTTP endpoint that accepts Flight payloads from the browser and decodes them on the server.
The root cause: unsafe deserialization
The server has to rebuild objects from the bytes a client sends. In the affected versions, the decoding logic did not strictly check what the payload referred to. A crafted payload could point at things the developer never meant to expose, and walk its way from "data I was given" to "code I can run".
The vulnerable packages were the React server packages, react-server-dom-webpack, react-server-dom-parcel and react-server-dom-turbopack, in the 19.x line. Next.js 15.x and 16.x apps using the App Router pulled them in. An app did not need to define any Server Function of its own to be reachable; having the endpoint was enough.
Why a "deserialization bug" is so dangerous
This is the same family of bug as Java serialization attacks and Python pickle problems. The common thread:
# The pattern, in the simplest form. Never do this with data from outside.
import pickle
obj = pickle.loads(request_body) # the sender decides what code runs
When a format can describe behaviour as well as data, whoever controls the bytes controls the program.
What to do
- Upgrade. Move to the patched React and Next.js versions listed in the advisories. Check
package.jsonand the lockfile, not just what you think you installed. - Rebuild and redeploy. The fix is in your dependencies, so it is not live until the new build is running.
- Do not rely on a WAF alone. Rules may help as a stopgap, but the fix is the upgrade.
- Assume exposure if you were unpatched. Check logs from around the disclosure date, look for unexpected processes and rotate secrets the server could read.
What to take away
- Anything parsed from the network is hostile until proven otherwise. That includes your own framework's internal protocol.
- Deserialization is a security boundary. If a decoder can instantiate or call things, restrict it to an explicit allow-list.
- Frameworks widen your attack surface quietly. Know which endpoints your framework creates for you.
- Patch speed is a feature. The time between a public advisory and active exploitation can be hours. Make sure you can rebuild and ship on the same day.
Resources
Official advisory
- Critical Security Vulnerability in React Server Components · The React team's announcement with the affected and fixed versions.
- Next.js security advisory: CVE-2025-66478 · The matching advisory for Next.js App Router apps.
Reference
- CVE-2025-55182 in the National Vulnerability Database · The CVE record and its severity score.