Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2025-55182 — Pre-auth RCE in React Server Components versions 19.0.0, 19.1.0, 19.1.1, and 19.2.0. | Kitploit
Tools/GitHubGitHub/dwisiswant0/cve-2025-55182
Vulnerability AnalysisCode AnalysisExploitationWeb Application ExploitationLearning & EducationPayload Development
GitHubdwisiswant0/cve-2025-55182

CVE-2025-55182

Pre-auth RCE in React Server Components versions 19.0.0, 19.1.0, 19.1.1, and 19.2.0.

View Repository
59158 months agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2025-55182

This repository contains a PoC reproduction of CVE-2025-55182, a critical security vulnerability in React Server Components (RSC) that allows unauthenticated arbitrary code execution.

Description

The vulnerability exists in how React Server Components deserialize "Server Actions" from client requests. Specifically, the requireModule function failed to validate that the requested export name was a direct prop of the module. This allowed attackers to access the constructor prop of exported functions, obtaining a reference to the global Function constructor, which can be used to execute arbitrary code.

Reproduction

This PoC uses a minimal Node.js environment to isolate the vuln in the react-server-dom-webpack library, just to make sure that the exploit demonstrates the bug in the library itself, NOT a misconfiguration in a framework.

Prerequisites

  • Node.js
  • npm

Installation

root@kitploit:~
npm install

[!NOTE] The package.json is pinned to the vulnerable version 19.0.0.

Proof of Concept

  1. Start the vulnerable server

This script sets up a raw HTTP server that uses the vulnerable React runtime to decode requests.

root@kitploit:~
# tty1
node --conditions react-server server.js
  1. Run the exploit script

In a separate terminal, run the exploit. This sends a malicious Flight payload to the server.

root@kitploit:~
# tty2
node exploit.js id

You should see the command output returned in the response:

Expected Output:

root@kitploit:~
Response: uid=0(root) gid=0(root) groups=0(root)

Analysis

Why did the vulnerability happen?

The requireModule function in ReactFlightDOMServerNode.js basically just trusted whatever name the client sent. It did moduleExports[metadata[NAME]] without checking whether that property was actually meant to be exposed. So if the client said "bro, I want this property", the server just said "sure thing! here you go, dawg".

Why is letting people access any property a bad idea?

Because it basically lets anyone reach into the prototype chain, even the constructor, which is super dangerous. If the module happens to export a function (like module.exports = () => {}), then its constructor is literally the global Function constructor.

Why does getting the Function constructor mean RCE?

Once an attacker grabs the Function constructor, they can abuse the "Bound Server Action" feature. They bind a string containing malicious JavaScript to it (basically turning it into new Function("evil code")). And once that runs, the server executes whatever code they put in.

Why would React actually run that malicious function?

Because Server Actions can be triggered by ID. If the attacker crafts a payload with an Action ID that points to their module#constructor reference, React resolves it like a normal action and executes it. That "action" is actually their malicious function.

Why wasn't any of this validated?

The system just assumed that id and name from the Server Reference metadata would always refer to valid exports defined by the developer. There was no safety check like hasOwnProperty to make sure the requested prop was actually a real export and not something inherited from the prototype chain.

Why server.js instead of Next.js?

I use a raw server.js (and a helper webpack-runtime.js) to manually configure the React Server Components runtime. This allows us to:

  1. Force the vulnerable setup: The exploit only works if a module is exported as a function (module.exports = fn)s. A real bundler might change how exports are wrapped, depending on its config tho.
  2. Isolate the bug: This lets us show the problem is inside react-server-dom-webpack, not Next.js.
  3. Recreate the bundler environment: react-server-dom-webpack assumes it's running inside a Webpack bundle. Our webpack-runtime.js gives it the globals it expects (__webpack_require__, __webpack_chunk_load__). This is not mocking the vuln, it's just giving the library the bare minimum runtime it needs to actually work.

Notes

There has been discussion about "Invalid PoCs" that only work if the developer purposely exposes dangerous stuff such as child_process.exec.

This PoC is not one of those. It works on a normal, safe setup.

  1. The exposed function is harmless The app exposes a simple updateProfile function that just returns a string and nothing sketchy, no shell commands.

  2. The exploit fully escapes that function The vulnerability lets the attacker ignore the safe export and jump straight to updateProfile.constructor, which is the global Function constructor.

  3. The core issue is the property access React should NOT have allowed access to .constructor. The developer did not intend to expose the Function constructor, instead, the insecure deserialization did that for them.

The only real requirement is that the module exports a function directly (module.exports = fn), which is super common in CommonJS and many bundler setups.

The Payload

The payload in exploit.js crafts a React Flight message with three chunks:

  • Chunk 0: Points to a Server Reference defined in Chunk 1.
  • Chunk 1: Declares the Server Reference:
    • id: "user-profile-action#constructor", meaning "give me the constructor".
    • bound: points to Chunk 2, which contains the arguments.
  • Chunk 2: ["console.log('nice try, diddy!')"]: the malicious code string.

When React deserializes this:

  1. It resolves user-profile-action.
  2. Reads the .constructor property => getting the global Function.
  3. Binds the attacker-provided string to it.
  4. Effectively executes: new Function("console.log('nice try, diddy!')")

And that's the RCE!

Mitigation

Upgrade immediately to the patched versions:

  • react-server-dom-webpack >= 19.0.1
  • react-server-dom-parcel >= 19.0.1
  • react-server-dom-turbopack >= 19.0.1

The patch introduces hasOwnProperty checks to prevent accessing inherited properties and restricts base64 file uploads.

If you run this PoC against a patched version, the server will crash or error with:

root@kitploit:~
$ node --conditions react-server server.js
Listening on http://localhost:3000
/path/to/CVE-2025-55182/node_modules/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js:2726
            resolvedValue = resolvedValue.bind.apply(
                                          ^

TypeError: Cannot read properties of undefined (reading 'bind')
    at /path/to/CVE-2025-55182/node_modules/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js:2726:43
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

Node.js v20.19.3

This confirms that the exploit failed to access the constructor property (it returned undefined instead of Function), and thus the subsequent .bind call failed.

Disclaimer

This code is for educational and testing purposes only. Do not use this exploit against systems you do not own or have explicit permission to test.

License

Released under DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE.

Download Tool