CVE-2025-55182 (“React2Shell”) is a critical Remote Code Execution (RCE) vulnerability in React Server Components (RSC) and Next.js App Router deployments using the vulnerable Flight protocol implementation. An unauthenticated attacker can abuse unsafe deserialization and prototype traversal to coerce the runtime into constructing and invoking arbitrary functions on the server.

Executive Overview & Impact

Severity CVSS 10.0 — Critical RCE

React2Shell affects applications using vulnerable versions of React’s RSC implementation and frameworks that bundle the Flight protocol, most notably Next.js App Router. A successful exploit yields:

  • Unauthenticated remote code execution within the server process.
  • Execution in the same privilege context as the Next.js runtime (often container root).
  • Direct access to environment variables, service credentials, and attached storage.
  • Potential lateral movement from the application tier into CI agents or underlying hosts.

Patches were released in React 19.2.1+ and in corresponding Next.js (e.g. 16.0.7 and later). Unpatched deployments remain viable RCE targets even when sitting behind standard WAFs and reverse proxies.

Key Observation
The exploit chain resides entirely inside the Flight request/response machinery: traditional WAF deployments that only understand HTTP and JSON see “valid” multipart form posts and do not track the internal object graph corruption caused by the payload.

3. Technical Root Cause

The vulnerability is the result of two cooperating flaws in the RSC deserializer: an unconstrained property traversal bug and an uncontrolled property assignment bug. Together, they give an attacker the ability to resolve arbitrary prototype-chain values and then persist them into security-sensitive locations.

3.1 Flight references and getOutlinedModel
Flight encodes references to previously deserialized objects in string form, such as “$1:someProp:nestedKey”. The helper responsible for resolving these references splits the string on : and iteratively indexes into the object:

// Simplified conceptual example (not exact vendor code)
for (let i = 1, obj = map[id].value; i < segments.length; i++) {
obj = obj[segments[i]]; // traverses arbitrarily deep, no allowlist
}
return obj;

Crucially, this traversal does not constrain which properties may be accessed. An attacker can therefore supply crafted segments such as “constructor” and “prototype” to climb the JavaScript prototype chain and eventually resolve to the built-in Function constructor.

3.2 reviveModel and uncontrolled write-back
Once values are resolved, the deserializer walks over object properties and writes back the “revived” values:

// Conceptual deserializer loop
for (const key in value) {
  const revived = reviveModel(response, value, key, value[key]);
  if (revived !== undefined) {
    value[key] = revived;   // arbitrary properties may be overwritten
  }
}

No validation is applied to either keys or resolved values. If an attacker can cause the traversal logic to return a powerful primitive (for example the Function constructor), they can overwrite internal fields such as _formData.get with that constructor. Later stages of the Flight parser that expect a benign accessor will instead invoke a powerful, attacker-controlled function.

Exploit Chain: From Data Chunk to Server-Side Logic

The React2Shell exploit is best understood as a four-stage chain, executed entirely through specially crafted Flight chunks. The exact on-wire encoding differs between frameworks, but the high-level mechanics are consistent.

Stage Mechanism Attacker Goal
1 — Pointer hijack Crafted reference causes traversal through prototype chain, resolving to the Function constructor. Obtain a powerful primitive embedded in the deserialization state.
2 — State corruption Using the uncontrolled assignment in reviveModel, the resolved constructor overwrites an internal method. Redirect control flow to attacker-controlled logic later in the pipeline.
3 — Payload injection A subsequent chunk carries a string containing the server-side behaviour, stored as a benign-looking property. Provide the source text that will later be turned into a function body.
4 — Invocation During finalization of the response, the overwritten callback is invoked and runs the constructed function. Execute arbitrary JavaScript with the permissions of the Next.js process.
Full React2Shell

Figure 1 — High-level React2Shell chain: malicious RSC request → Flight parser → prototype traversal → internal state overwrite → unexpected server logic.

5. Dynamic Workflow

This section provides per-function workflow graphs for the main moving parts of the vulnerability. The Mermaid-style prompts remain documented here for reproducibility, while the article uses the embedded PNG diagrams for presentation.

5.1 getOutlinedModel prototype traversal


  A[Flight chunk carries a reference value] --> B[Parser reads a string like "$id:field1:field2:..."]
  B --> C[Split the string on ":" into parts[]]
  C --> D[Use parts[0] (id) to look up the base object in a map]
  D --> E[Loop over the remaining parts one by one]
  E --> F[If part is a normal field name, read base[part]]
  E --> G[If part names constructor / prototype or similar, move along the JS prototype chain]
  F --> H[Update base as you walk legitimate fields]
  G --> H[Update base while climbing the prototype chain]
  H --> I[After the last part, you end up with a final resolved value]
  I --> J[Return that value and store it back into the deserialization state]
1

Figure 2 — Prototype traversal in getOutlinedModel: from benign references to resolving a powerful constructor via the prototype chain.

5.2 reviveModel uncontrolled assignment


  A[Deserializer holds object "value"] --> B[Loop over each key in value]
  B --> C[Call reviveModel(response, value, key, value[key])]
  C --> D[Check if reviveModel returned a new value]
  D -- yes --> E[Assign value[key] = revived value]
  D -- no --> F[Leave this property as-is]
  E --> G[If key is a normal field, this is a harmless state update]
  E --> H[If key is an internal field like "_formData.get", overwrite a critical function]
  H --> I[Overwritten function pointer remains in the parser state]
  I --> J[Later code calls this field and unknowingly executes attacker-chosen logic]
2

Figure 3 — Uncontrolled write-back in reviveModel, allowing sensitive internal callbacks to be overwritten with attacker-influenced values.

5.3 Callback hijack & processing flow


  A[Internal callback has already been overwritten] --> B[Another Flight chunk arrives]
  B --> C[This chunk contains an attacker-controlled string payload]
  C --> D[Framework prepares to resolve an action or response]
  D --> E[Framework invokes the internal callback with the payload string]
  E --> F[Callback builds a new function from the supplied string]
  F --> G[New function is executed inside the Node.js process]
  G --> H[Code now runs with the application's privileges and can touch filesystem, env, or network]
3

Figure 4 — Callback hijack: once the internal callback is replaced, subsequent chunks cause the framework to construct and run new server-side logic from supplied strings.

5.4 End-to-end exploit chain


  A[Attacker crafts a malicious RSC request] --> B[Request hits the RSC / Flight parser]
  B --> C[First chunk carries a crafted reference path]
  C --> D[getOutlinedModel walks the path and resolves a powerful primitive]
  D --> E[reviveModel writes that primitive into a sensitive internal field]
  E --> F[Parser state now holds an attacker-chosen callback]
  F --> G[Second chunk delivers an attacker-controlled payload string]
  G --> H[Overwritten callback builds and runs a new server-side function]
  H --> I[Function executes inside the application process]
  I --> J[Attacker can read data or perform further actions, depending on the code executed]
full-0

Figure 5 — Compact view of the full React2Shell chain, aligning protocol-level events with internal runtime transitions.

6. Detection & WAF Evasion

React2Shell is particularly challenging for traditional perimeter security because the exploit
leverages semantically valid protocol messages rather than obviously malicious payloads.

6.1 Why generic WAF signatures struggle

  • Custom protocol surface: Flight encodes references and payloads using a
    bespoke syntax ($id markers, colon-separated paths, base64-like segments) wrapped in
    multipart/form-data. Most WAFs treat this as opaque text.
  • Application-internal corruption: The dangerous part of the exploit is the
    reassignment of in-memory fields such as _formData.get. This behaviour is invisible on the
    wire and only observable inside the runtime.
  • Legitimate-looking control flow: The final invocation occurs as part of
    normal promise resolution inside the RSC implementation; network logs only show ordinary HTTP 200/500
    responses.

6.2 Practical detection strategies

  • Flag or block unauthenticated POSTs with Content-Type: multipart/form-data that
    also include Next-Action or similar RSC-specific headers.
  • Alert on bodies that contain $-prefixed identifiers combined with long colon-separated
    reference chains, especially when targeting action endpoints.
  • Correlate sudden spikes in HTTP 500 responses for RSC endpoints with anomalous multipart requests.

6.3 Runtime and observability signals

  • Any usage of child_process.* from within Next.js server bundles.
  • Dynamic calls to Function, eval, or similar constructors originating from RSC
    modules.
  • Process-level anomalies such as short-lived shells, unexpected outbound connections, or
    access to sensitive paths from the application container.

7. Remediation & Hardening

Given active exploitation and the ease of weaponization once details are known, React2Shell should
be treated as a patch-out-of-band event rather than a routine maintenance item.

7.1 Immediate actions

  • Patch React / Next.js: Upgrade all RSC-enabled applications to
    React 19.2.1+ and a patched version of Next.js (for example 16.0.7 or the latest
    stable in your channel). Ensure lockfiles are updated and rebuilt.
  • Invalidate builds: Rebuild all containers and serverless artefacts from a
    clean state to ensure no old runtime images linger in production or staging.
  • Credential hygiene: If exploitation is suspected, rotate environment
    credentials (database users, API keys, cloud roles) that were accessible to the application.

7.2 Medium-term hardening

  • RSC exposure review: Limit where RSC actions are exposed; prefer internal
    networks or authenticated sessions for state-changing operations.
  • Runtime guards: Introduce application-level checks that block access to
    dangerous prototype paths and prevent assignment of constructors or built-ins into non-code fields.
  • RASP / in-process monitoring: Deploy runtime protection that can detect
    abnormal prototype traversal, reflection abuse, and process-spawning behaviours.
  • Defence-in-depth: Use seccomp/AppArmor, constrained container users, and
    network policies so that even a successful React2Shell exploit has limited blast radius.

7.3 Secure development practices

  • Adopt secure deserialization patterns throughout server code: never traverse paths from
    user-controlled strings without explicit allowlists.
  • Include prototype pollution and RSC-specific checks in internal security reviews and
    SAST/DAST pipelines.
  • Establish canary environments where RSC features are rolled out under heightened
    telemetry before widespread adoption.

8. Timeline (React2Shell / CVE-2025-55182)

  • Late Nov 2025 — Vulnerability reported to React/Vercel teams; coordinated response initiated.
  • 3 Dec 2025 — CVE-2025-55182 assigned with Critical severity (CVSS 10.0).
  • Early Dec 2025 — Proof-of-concepts and scanning rules appear; first exploitation attempts observed in the wild.
  • Patch window — React 19.2.1 and patched Next.js releases become available; vendors update advisories.
  • Ongoing — Ecosystem-wide hardening and additional protocol safeguards evaluated for future RSC iterations.

9. References

  1. Official React / Next.js security advisories for CVE-2025-55182 and related RSC issues.
  2. Vendor write-ups and threat-intel blogs analysing RSC Flight protocol weaknesses and prototype traversal classes of bugs.
  3. General guidance on secure deserialization and prototype-pollution mitigation in JavaScript runtimes.