Date Mar 31, 2026

React2Shell (CVE-2025–55182) Explained for Mere Mortals

CVE-2025-55182 is a critical unauthenticated Remote Code Execution vulnerability in React Server Components — dubbed React2Shell. Before diving into the exploit, you need to understand three key JavaScript concepts that make it possible: Function constructors, getting the constructor from objects, and thenables.

React2Shell CVE-2025-55182

Concept 1: Function Constructors in JavaScript

In JavaScript, it's possible to create a function using the Function() constructor. You can create an empty function or one with a body by passing a string:

// Empty function — equivalent to: function myfunc() {} var myfunc = Function() // Function with a body — the string becomes the function body var myfunc = Function("alert(123)") // Equivalent to: function myfunc() { alert(123); } // With parameters var myfunc = Function("x", "alert(x)") // Equivalent to: function myfunc(x) { alert(x); }

Concept 2: Getting the Function Constructor from Objects

Functions in JavaScript are objects, so they have a constructor. You can retrieve the Function constructor from any function — including those attached to plain objects:

// alert.constructor IS Function() since alert is a function var myfunc = alert.constructor("alert(123)") // From a plain object, via any method: var myobj = {}; var myfunc = myobj.toString.constructor("alert(123)") // Or through the constructor chain: var myfunc = myobj.constructor.constructor("alert(123)") var myfunc = myobj.__proto__.constructor.constructor("alert(123)")

Concept 3: Thenables

A "thenable" is an object with a then property that is a function. When you await a thenable, JavaScript calls its then function:

var thenable = { then() { alert(12); } } await thenable; // ← triggers alert(12)! // Combining with the constructor trick: var thenable = { "then": {}.toString.__proto__.constructor }

React Flight Protocol

React uses a protocol called the React Flight Protocol to serialize objects. Data is organized into numbered chunks that can reference each other using $N syntax:

files = { "0": (None, '["$1"]'), "1": (None, '{"object":"fruit","name":"$2:fruitName"}'), "2": (None, '{"fruitName":"cherry"}'), } // After resolution: { object: 'fruit', name: 'cherry' }

The Vulnerability

React did not validate the key used to access a chunk property. Built-in JavaScript properties like __proto__, constructor, and constructor.constructor (the Function constructor) were all accessible through the chunk reference syntax:

files = { "0": (None, '["$1:__proto__:constructor:constructor"]'), "1": (None, '{"x":1}'), } // Deserialized result: [Function: Function]

Executing Arbitrary Functions via Thenables

React's processing function uses await on the deserialized result. By setting then to the Function constructor, the await call triggers code execution:

files = { "0": (None, '{"then":"$1:__proto__:constructor:constructor"}'), "1": (None, '{"x":1}'), } // This triggers: SyntaxError: Unexpected token 'function' // — because React awaits our thenable, calling Function() as `then`

Gaining Full Code Execution

Researcher maple31426 discovered a $@ "raw chunk" reference whose prototype already has a then method defined by React itself — and a resolved_model status code path that calls initializeModelChunk(this). By combining all three concepts, an attacker can pass arbitrary code to the Function constructor via _response._prefix and achieve reliable RCE on any server running React Server Components.

Key Exploitation Steps

  • Step 1 — Get the raw chunk reference: Use $@ syntax to reference the "raw" version of a chunk, which already has a then method.
  • Step 2 — Trigger initializeModelChunk: Set status: "resolved_model" to force React's switch statement to call the vulnerable function.
  • Step 3 — Enter the Blob handler: Set value: "$B0" to reach the response._formData.get(response._prefix + obj) code path.
  • Step 4 — Replace .get with Function constructor: Set _response._formData.get to $1:constructor:constructor.
  • Step 5 — Inject your code in _prefix: Any string placed in _response._prefix becomes the body of an executed function. Add // to comment out the trailing concatenation.

Mitigation

  • Upgrade immediately: Patch to a fixed version of React / Next.js (Next.js 15.0.5, 15.1.9, 15.2.6, 15.3.6, 15.4.8, 15.5.7, 16.0.7 or later).
  • Audit your exposure: Any default create-next-app production build with RSC enabled is exploitable out of the box.
  • Deploy WAF rules: Cloudflare, AWS WAF, and Google Cloud Armor have published rules for this CVE.
  • Enable runtime detections: Tools like Falco or Sysdig Secure can catch anomalous child process spawning.

Written by Fady Othman, Co-founder and Director of R&D at ZINAD.

Protect Your Applications with ZINAD

ZINAD's Application Security services include vulnerability assessments, secure code review, and developer training to help your teams stay ahead of critical vulnerabilities like React2Shell.

https://ZINAD.net/support-page.html