The custom streaming protocol underlying React Server Components, known as Flight, has been identified as a critical deserialization sink, leading to severe vulnerabilities including unauthenticated remote code execution (RCE). Security researcher Durgesh Pawar meticulously deconstructed the mechanics of the "React2Shell" vulnerability, officially designated CVE-2025-55182, which registered a maximum CVSS score of 10.0. This flaw demonstrated how manipulation of the Flight protocol, a mechanism designed to stream interactive UIs, could grant attackers full shell access to affected systems without requiring any authentication. The revelations have prompted an urgent reassessment of security practices for React applications, highlighting the inherent risks in custom deserialization systems and the need for robust defensive measures ranging from stringent schema validation to enhanced cross-site request forgery (CSRF) hardening.
The Rise of React Server Components and the Enigma of Flight
React Server Components (RSCs), introduced to enhance performance and developer experience, represent a paradigm shift in web development by enabling components to render entirely on the server and stream their output to the client. This approach allows for leaner client bundles, faster initial page loads, and direct database access from server-side logic, blurring the lines between traditional server-side rendering and client-side interactivity. Crucially, RSCs do not transmit traditional HTML or JSON to the browser. Instead, they leverage a proprietary, custom streaming protocol called Flight. This line-delimited format, with its own type system, reference resolution, and rules for reconstructing executable behavior, silently reassembles complex UI trees on the client side. Most React developers, focused on the framework’s powerful abstractions, rarely inspect the Flight payload directly, often placing implicit trust in the underlying mechanism.
Unveiling React2Shell: A CVSS 10.0 Vulnerability
The implicit trust in the Flight protocol was fundamentally challenged in December 2025 with the public disclosure of CVE-2025-55182, swiftly dubbed "React2Shell" by the security community. This vulnerability represented an unauthenticated remote code execution flaw residing deep within the Flight deserialization layer. Its CVSS 10.0 rating underscored the maximum possible severity: a single, specially crafted HTTP request targeting a Server Function endpoint was sufficient for an attacker to gain unauthenticated shell access. This meant full system compromise without the need for any credentials or prior authentication. The U.S. federal Cybersecurity & Infrastructure Agency (CISA) immediately added CVE-2025-55182 to its Known Exploited Vulnerabilities catalog, signaling its critical nature and active exploitation in the wild. This rapid, high-level response and the vulnerability’s perfect score highlighted a fundamental weakness that had previously gone unnoticed in the widely adopted framework.
Timeline of Disclosure and Exploitation
The timeline surrounding React2Shell demonstrates the rapid pace at which critical vulnerabilities in widely used frameworks can be weaponized:
- December 2025: CVE-2025-55182 (React2Shell) is publicly disclosed. The security community immediately recognizes its severity due to the CVSS 10.0 rating and unauthenticated RCE nature.
- Hours after disclosure: Sysdig, a prominent cloud security company, publishes urgent research linking in-the-wild exploitation of React2Shell to North Korean state-sponsored actors. These groups were observed deploying EtherRAT, a sophisticated file-less implant that uniquely utilizes the Ethereum blockchain for command-and-control (C2) communications. This "EtherHiding" technique makes C2 infrastructure virtually impossible to detect and take down due to the decentralized and immutable nature of the blockchain.
- Shortly thereafter: Palo Alto Networks’ Unit 42, another leading cybersecurity firm, documents the deployment of a separate backdoor named KSwapDoor. This malware was designed to masquerade as
[kswapd1]on infected Linux systems, blending into process lists alongside the legitimatekswapd0kernel swap daemon. KSwapDoor employed robust RC4 encryption for internal strings and configuration data, while its C2 communications ran over AES-256-CFB with Diffie-Hellman key exchange across a peer-to-peer mesh network, showcasing advanced stealth and resilience. - December 2025 onwards: The initial disclosure triggers intensive security audits, leading to the discovery of a series of related vulnerabilities in the same deserialization surface. These require multiple rounds of patches from the React team:
- CVE-2025-55184 (DoS, CVSS 7.5): Disclosed shortly after React2Shell, this flaw involved an infinite recursion of nested Promises within Server Function deserialization, capable of hanging the Node.js event loop and causing a denial of service.
- CVE-2025-55183 (Information Disclosure, CVSS 5.3): This bug allowed crafted requests to reflect Server Function source code when an argument was stringified (a common practice for logging or debugging), potentially exposing sensitive business logic or hardcoded secrets.
- CVE-2025-67779 (DoS, CVSS 7.5): Identified as an incomplete fix for CVE-2025-55184, this required a second patch to address missed edge cases in the Promise recursion, further illustrating the complexity of securing deserialization parsers.
- January 2026: CVE-2026-23864 (DoS/OOM, CVSS 7.5) is disclosed. This vulnerability exposed a risk of memory exhaustion through unbounded request body buffering and zipbomb-style decompression attacks, leading to potential server crashes.
- Later in 2026: CVE-2026-27978 (CSRF Bypass, CVSS 5.3) in Next.js Server Action handling is identified. This flaw occurred because Next.js incorrectly treated
Origin: null(sent by sandboxed iframes) as a "missing" origin rather than an explicit cross-origin indicator, allowing attackers to bypass CSRF protections.
The swift weaponization by state-sponsored groups underscores the critical nature of such flaws in foundational web technologies. The immediate deployment of sophisticated implants through a single unauthenticated HTTP request highlights why deserialization vulnerabilities in core frameworks demand immediate attention and patching, as they present an attractive target for high-impact cyber operations.

The Technical Underpinnings: Flight as a Deserialization Sink
At its core, the Flight protocol is not merely a data format; it is a deserialization system. Unlike plain JSON, which only yields inert data, Flight reconstructs behavior. It interprets module references to load client-side code, establishes server action endpoints for remote procedure calls (RPC), sets up Promise chains for asynchronous operations, and builds lazy-loaded component boundaries that execute on demand. This dynamic reconstruction of executable elements from a text stream introduces an inherent attack surface, reminiscent of historical deserialization vulnerabilities in other languages like Java’s ObjectInputStream (which famously led to the ysoserial toolkit), Python’s pickle (known for executing arbitrary code on load()), PHP’s unserialize (exploited via __wakeup and __destruct methods), and .NET’s BinaryFormatter (eventually deprecated entirely due to security risks). The pattern is consistent: deserialize attacker-controlled input, invoke behavior during reconstruction, and consequently lose control of execution.
The vulnerability in Flight primarily stems from its sophisticated prefix system. While a simple Flight payload might appear benign, with rows representing import directives (e.g., 1:I[...]), JSON trees (2:J[...]), or server context data (0:D[...]), the real danger lies in the $ prefix system. This system allows the client-side parser, specifically the parseModelString function in ReactFlightClient.js, to intercept strings starting with $ and route them through type-specific resolution paths. This mechanism effectively drives the parser’s control flow based on the stream’s content.
Key problematic prefixes include:
$:(Property Access): This prefix allows traversal into resolved chunks’ properties, e.g.,$1:user:name. This capability for arbitrary property traversal, driven directly by the incoming data stream, is a classic vector for prototype pollution. In JavaScript’s prototype-based inheritance, manipulating__proto__orconstructor.prototypecan modify shared base prototypes that all objects inherit from, allowing attackers to inject controlled values that downstream code will unknowingly use.$@(Promise/Raw Chunk): This prefix exposes the raw internalChunkobject, which React uses to track resolution state and pending callbacks. While intended for Promises, it provides a mutable handle to internal framework plumbing, a design choice that exposes unnecessary internal state and can be abused.$F(Server Reference): Represents a callable Server Action, an RPC endpoint on the server. Forging these references could lead to unauthorized function invocations or parameter tampering.
The combination of arbitrary property traversal and the ability to reconstruct executable elements (like lazy-loaded components or server RPC endpoints) means the Flight protocol instructs the client runtime on what code to load, what functions to call, and what to trust, all driven by potentially malicious input. This level of dynamic behavior reconstruction from untrusted data is a significant security concern.
The Mechanics of React2Shell: A Prototype Pollution Gadget Chain
The core vulnerability in React2Shell (CVE-2025-55182) was found within the getOutlinedModel function, specifically in the server-side reply handling code (ReactFlightReplyServer.js). This function is responsible for resolving deep property paths from the $: reference system. The critical flaw lay in a loop that traversed colon-separated path segments without adequate validation:
for (key = 1; key < reference.length; key++)
parentObject = parentObject[reference[key]];
This two-line snippet lacked a hasOwnProperty check, which would verify if a property truly belongs to an object instance rather than being inherited from its prototype chain. Without this check, property lookups could ascend the prototype chain. An attacker could supply a reference like $1:__proto__:constructor:constructor. This path would traverse from a basic JSON object, up through Object.prototype, to the Object constructor, and ultimately to the Function constructor. In JavaScript, Function("arbitrary code")() acts as an eval() equivalent, enabling the execution of arbitrary code within the Node.js environment.
The full gadget chain, as detailed by security researchers like Resecurity, composed several legitimate Flight protocol features to achieve RCE:
- Arbitrary Prototype Pollution: The
$:__proto__:constructor:constructorpath was used to gain access to theFunctionconstructor. - Abusing Thenables: The attacker crafted an object with a manipulated
.thenproperty. The V8 JavaScript engine (and the language specification) treats any object




