React2Shell (CVE-2025-55182) Deserialization to Remote Code Execution in React and Next.js - Checkmarx
← Zero Blog

React2Shell (CVE-2025-55182) Deserialization to Remote Code Execution in React and Next.js

React2Shell (CVE-2025-55182) is a critical unauthenticated RCE vulnerability in React and Next.js caused by insecure deserialization, putting a large number of applications at immediate risk.

React, a JavaScript library for building user interfaces, and one of the most widely used NPM libraries with over 50M weekly downloads, released an advisory (CVE-2025-55182, CVSSv3.1 = 10.0) on December 3, 2025, warning users that the React Server Components (RSC), including the react-server-dom-parcel, react-server-dom-turbopack, and react-server-dom-webpack NPM packages, are vulnerable to a Remote Code Execution (RCE) attack. This vulnerability, now referred to as React2Shell in the security community, allows an unauthenticated attacker to craft a malicious HTTP request to any Server Function endpoint and trigger insecure deserialization, leading to remote code execution on the server.

Mitigation of this risk is difficult; upgrade following the guide in the table below

Even if no specific endpoints are in use, supporting React Server Components can leave users vulnerable, further increasing the criticality of this issue.

The scope of React2Shell extends beyond React, affecting Next.js, a full-fledged React framework and one of the most widely used JavaScript frameworks with over 130k GitHub stars, as well as other projects that use React or Next.js.

Below, we share a table of the main affected packages and the fixed versions.

If your project uses any of the dependencies listed below, please update them to the latest version as specified in the corresponding update action. Most dependencies have a single update action, but Next.js includes separate update actions for each branch.

Project Affected branches Fixed versions Update Action
React 19.0.x 19.1.x 19.2.x 19.0.1 19.1.2 19.2.1 npm install react@latest
React Router All that contain the dependencies listed in the update action Any version in which the “Update Action” was executed npm install react@latest react-dom@latest react-server-dom-parcel@latest react-server-dom-webpack@latest @vitejs/plugin-rsc@latest
react-server-dom-parcel 19.0.x 19.1.x 19.2.x 19.0.1 19.1.2 19.2.1 npm install react@latest react-dom@latest react-server-dom-parcel@latest
react-server-dom-webpack 19.0.x 19.1.x 19.2.x 19.0.1 19.1.2 19.2.1 npm install react@latest react-dom@latest react-server-dom-webpack@latest
react-server-dom-turbopack 19.0.x 19.1.x 19.2.x 19.0.1 19.1.2 19.2.1 npm install react@latest react-dom@latest react-server-dom-turbopack@latest
Next.js 14.3.0-canary 15.0.x
15.1.x
15.2.x
15.3.x
15.4.x
15.5.x
16.0.x
14.3.0-canary.88 15.0.5
15.1.9
15.2.6
15.3.6
15.4.8
15.5.7
16.0.7
One of:
npm install next@14
npm install [email protected]
npm install [email protected]
npm install [email protected]
npm install [email protected]
npm install [email protected]
npm install [email protected]
npm install [email protected]
@vitejs/plugin-rsc All 0.5.3 npm install react@latest react-dom@latest @vitejs/plugin-rsc@latest
Redwood SDK All 1.0.0-beta36 npm install react@latest react-dom@latest react-server-dom-webpack@latest rwsdk@latest
Waku All 0.27.3 npm install react@latest react-dom@latest react-server-dom-webpack@latest waku@latest

Note that this is only an overview of affected packages that were already disclosed by official sources. Any other application using React Server Components by importing a vulnerable version or bundling vulnerable code is likely affected as well.

How is React Impacted?

In the blog post shared by the React team, it’s clear that React2Shell originates in the React Server Components (RSC). RSC is a feature that allows React components to run exclusively on the server, offering significant performance benefits and giving developers greater flexibility in how their components behave.

Server Components can expose specific functions that Client Components can call asynchronously. These are known as Server Functions. To achieve this communication between server and client components, React implemented the Flight Protocol, an internal serialization format that transmits rendered components and data. The Flight protocol handles two critical flows:

Server-to-Client Flow (Standard):

  • Server renders components and serializes output
  • Flight protocol streams data packets to the client
  • Client deserializes and renders UI

Client-to-Server Flow (Reply Flow):

  • Client serializes form submissions or function calls
  • Flight protocol transmits data to the server
  • Server deserializes and processes requests

To simplify, when a Client Component calls a Server Function, React translates that call into an HTTP request that is forwarded to the server. On the server, React translates the HTTP request into a function call, via deserialization, and returns the needed data to the client. This is achieved through the Flight protocol.

Since React translates these server functions into HTTP requests and deserializes the request on the server side, we can already picture how this can be exploited. It is possible for an unauthenticated attacker to craft a malicious HTTP request to any Server Function endpoint that, when deserialized by React, achieves remote code execution on the server.

Another Day, Another Deserialization Disaster

The vulnerability resides in the client-to-server reply flow, specifically in how the server deserializes incoming requests to resolve Server Actions—functions that execute on the server in response to client interactions.

React Server Actions enable client components to invoke server-side functions. When a client submits a form or calls a server action, React serializes the request using a specific format:

$ACTION_ID: "module-id#export-name"

The server receives this identifier and uses it to resolve the corresponding function. This process involves three steps:

  • Parse the action ID – Split on ‘#’ to extract module ID and export name
  • Load the module – Use __webpack_require__ to load the module
  • Access the export – Retrieve the function using bracket notation: moduleExports[exportName]

The vulnerability exists in step 3—accessing the export. Here’s the actual vulnerable code from React’s Flight protocol implementation in the `requireModule` function:

export function requireModule<T>(metadata: ClientReference<T>): T {
  let moduleExports = __webpack_require__(metadata[ID]);
  if (isAsyncImport(metadata)) {
    if (typeof moduleExports.then !== 'function') {
      // This wasn't a promise after all.
    } else if (moduleExports.status === 'fulfilled') {
      // This Promise should've been instrumented by preloadModule.
      moduleExports = moduleExports.value;
    } else {
      throw moduleExports.reason;
    }
  }
  if (metadata[NAME] === '*') {
    // This is a placeholder value that represents that the caller imported this
    // as a CommonJS module as is.
    return moduleExports;
  }
  if (metadata[NAME] === '') {
    // This is a placeholder value that represents that the caller accessed the
    // default property of this if it was an ESM interop module.
    return moduleExports.__esModule ? moduleExports.default : moduleExports;
  }
  return moduleExports[metadata[NAME]];
///....
}

The issue is in the final line moduleExports[metadata[NAME]].

Because React’s code didn’t verify that the requested property was an own property of the module (meaning a property defined directly on the module object, not inherited), attackers could access these inherited properties, including methods outside the object’s property scope that should never be accessible.

Exploiting the React2Shell vulnerability

Modern JavaScript applications commonly bundle dangerous Node.js modules for legitimate purposes. These modules become part of the webpack bundle during the build process.

When these modules exist in the webpack bundle, their exports become accessible through the module resolution mechanism. However, only modules already in the bundle can be exploited—attackers cannot load external modules from outside the bundle’s scope. Since dangerous modules are often included directly or as transitive dependencies, they commonly exist in production bundles. An attacker can craft a request that specifies one of these dangerous modules to achieve code execution:

$ACTION_ID: "vm#runInThisContext"

This instructs React to:

  1. Load the vm module (legitimate module in the bundle)
  2. Access vm['runInThisContext'] (legitimate export of vm module)
  3. Return the runInThisContext function to be invoked

The vm.runInThisContext function executes arbitrary JavaScript code in the current context—giving the attacker full code execution capabilities on the server.

Similarly, attackers can target:

  • child_process#execSync – Execute arbitrary shell commands
  • fs#readFileSync / fs#writeFileSync – Read or write arbitrary files

The presence of even one of these modules in the webpack bundle is sufficient for exploitation. Given how commonly these modules are included as transitive dependencies, the attack surface is significant.

How is Next.js Impacted?

Next.js is a comprehensive React framework and one of the most popular JavaScript frameworks, with over 130k GitHub stars. Because Next.js is built on top of React, it is also affected by React2Shell.

However, Next.js can be considered just another project impacted by the underlying React issue since it does not introduce any unique risks or behaviors beyond those already present in React itself.

To address the vulnerability in Next.js, the team released a commit (b1a04a8) that updated their compiled internal React code to incorporate the fix provided by React. Additionally, they upgraded the vulnerable React dependency packages to versions that include the patch.

To remediate the vulnerability in Next.js, check the branch you are currently using and upgrade to one of the versions found in the table at the top of this page.

Initially, CVE-2025-66478 was issued for the vulnerability in Next.js, but it was quickly rejected. The reason is that the vulnerability resides in the compiled React code included within Next.js. Since Next.js itself is not directly vulnerable, CVE-2025-66478 is considered a duplicate of CVE-2025-55182.

MITRE’s Rejection of CVE-2025-66478 (duplicate of CVE-2025-55182)

Conclusion

React2Shell (CVE-2025-55182) is undeniably a critical security issue. Not only because of its CVSS score of 10, which underscores its technical severity, but also because of the widespread usage of the affected projects. This vulnerability is an unauthenticated remote code execution issue in one of the most popular and widely used JavaScript libraries, React. Its reach extends beyond React itself since Next.js, one of the most popular JavaScript frameworks, is also affected by this vulnerability.

Get more like this in your inbox
visual

This is one of the most critical types of security vulnerabilities, impacting a large portion of the JavaScript ecosystem. The community is calling this vulnerability React2Shell because, like Log4Shell, it enables unauthenticated remote code execution and has similarly broad impact, severity, and reach across the ecosystem.

We at Checkmarx encourage all users to review their projects and dependencies and follow the table at the top of this page to guide you on how to properly remediate this vulnerability. SCA tools like the one available in the Checkmarx One platform will detect affected projects and suggest proper remediation actions.