Executive Overview
The evolution of modern web architecture has increasingly pushed computational workloads away from the client browser and back onto centralized servers. React Server Components (RSCs) epitomize this paradigm shift, allowing developers to render components on the server before transmitting them downstream. However, this architectural leap relies on a specialized mechanism: a custom streaming protocol known as Flight.
Unlike standard JSON or raw HTML, Flight is a line-delimited format equipped with its own type system, reference resolution, and instructions for reconstructing executable behavior in the browser. While innovative, this capability introduces powerful deserialization sinks.
In December 2025, security researcher Durgesh Pawar and the broader cybersecurity community brought this hidden attack surface to light with CVE-2025-55182, colloquially dubbed "React2Shell." Rated at a maximum CVSS 10.0 severity score, this unauthenticated remote code execution (RCE) vulnerability within the Flight deserialization layer allowed attackers to achieve full shell access via a single, maliciously crafted HTTP request.
This deep-dive investigation explores the underlying mechanics of the Flight protocol, dissects how structural protocol manipulation leads to complete infrastructure compromise, traces the exploitation timeline, and provides a prioritized, actionable set of defenses—from rigorous input validation schemas to CSRF hardening—to protect modern React and Next.js deployments.
Detailed Chronology: From Discovery to Exploitation
The discovery of CVE-2025-55182 marked a watershed moment for the React ecosystem, challenging the long-held assumption that JavaScript environments are inherently insulated from classic deserialization vulnerabilities.
The Vulnerability Disclosure (December 2025)
When CVE-2025-55182 dropped in December 2025, it caught many engineering teams off-guard. Because Flight payloads are handled entirely under the hood by frameworks like Next.js, few developers had ever inspected them within browser developer tools.
The Cybersecurity and Infrastructure Security Agency (CISA) promptly added the vulnerability to its Known Exploited Vulnerabilities (KEV) catalog, signaling the severity of the threat. Threat intelligence firms like Sysdig quickly linked in-the-wild exploitation attempts to North Korean state-sponsored actors, who deployed sophisticated file-less malware implants leveraging the Ethereum blockchain for command-and-control (C2) communication.
Subsequent Waves and Patch Iterations
Following the initial RCE disclosure, security audits of the Flight deserialization surface uncovered a cascading series of related vulnerabilities. The React core team rushed out patches, but the remediation process highlighted the intrinsic difficulty of securing complex deserialization parsers:
- CVE-2025-55184 & CVE-2025-67779 (CVSS 7.5): These Denial of Service (DoS) vulnerabilities involved infinite recursion bugs triggered by nested Promises during Server Function deserialization, effectively hanging the Node.js event loop. An initial patch missed several edge cases, requiring a secondary fix.
- CVE-2026-23864 (CVSS 7.5): Disclosed in January 2026, this vector enabled memory exhaustion (Out-Of-Memory/OOM) attacks through unbounded request body buffering and zipbomb-style decompression within the parsing pipeline.
- CVE-2025-55183 (CVSS 5.3): A critical information disclosure bug where crafted requests forced Server Functions to implicitly stringify arguments, inadvertently reflecting the server-side source code, database queries, and embedded environment secrets back in the HTTP response.
- CVE-2026-27978 (CVSS 5.3): A framework-level CSRF bypass in Next.js where requests originating from sandboxed
<iframe>elements (which supply anOrigin: nullheader) were incorrectly treated as "missing" rather than "cross-origin," allowing attackers to invoke authenticated Server Actions.
Supporting Context & Metrics: Anatomy of the Flight Protocol
To understand how React2Shell bypassed modern web defenses, one must first understand what travels across the wire during a Server Component render cycle.
Flight On The Wire
When inspecting network traffic on a Next.js App Router application, requests returning Content-Type: text/x-component reveal the Flight stream. Rather than a singular JSON payload, Flight is a streaming, line-delimited format where each line represents a self-contained "row" processed sequentially by the client-side React runtime.
A typical payload exhibits a structure similar to this:
1:I["./src/components/ClientComponent.js",["chunks/main.js"],"default"]
2:J["$","article",null,"children":"$1"]
0:D"name":"RootLayout","env":"Server"
Every row follows a strict syntax: <ROW_ID>:<ROW_TAG><PAYLOAD>n. The parser relies heavily on a specialized prefix system triggered by the dollar sign ($). When the runtime encounters a string starting with $, it routes the value through type-specific resolution paths in files like ReactFlightClient.js:
$(Model Reference): Resolves to another chunk ID in the stream (e.g.,$2).$:(Property Access): Performs arbitrary property traversal across resolved chunks (e.g.,$1:user:name).$F(Server Reference): Represents a callable Server Action (an RPC endpoint).$L(Lazy Component): Defers component loading until rendered.$@(Promise/Raw Chunk): Hands the caller the raw internalChunkwrapper object rather than its resolved value.
The Deserialization Sink
While languages like Java (ObjectInputStream) and Python (pickle) have long battled arbitrary code execution via deserialization, JavaScript developers historically relied on the safety of JSON.parse(), which produces inert data structures without triggering constructors or magic methods.
However, Flight transcends simple data transfer; it reconstructs behavior. By combining the $: property traversal prefix with duck-typing mechanisms (such as looking for .then properties to construct Thenables), the parser executes code paths driven entirely by incoming text streams.

The root cause of CVE-2025-55182 lay within getOutlinedModel (located in ReactFlightReplyServer.js), which handled deep property paths without proper ownership validation:
for (key = 1; key < reference.length; key++)
parentObject = parentObject[reference[key]];
Lacking a hasOwnProperty check, an attacker could supply a payload containing $1:__proto__:constructor:constructor, traversing from a plain JSON object up through Object.prototype to the global Function constructor. In JavaScript, invoking Function("arbitrary code")() executes native code, resulting in unauthenticated remote code execution.
Official Statements & Industry Impact
The security community’s response to React2Shell underscored a sobering reality: framework-level abstractions cannot entirely insulate developers from fundamental architectural risks.
Official advisories from the React core team detailed the implementation of a targeted patch designed to cache the genuine hasOwnProperty method at module load time:
var hasOwnProperty = Object.prototype.hasOwnProperty;
// Enforced via calling convention:
hasOwnProperty.call(value, i);
While this patch successfully neutralizes the specific prototype traversal gadget chain, security researchers have noted that it treats the symptom rather than the structural design choice. Exposing arbitrary property traversal and executable reference resolution through a network-facing text protocol remains an inherently brittle design paradigm.
Intelligence reports from firms like Palo Alto Networks (Unit 42) highlighted the speed at which advanced persistent threat (APT) groups operationalized the vulnerability. Their analysis of the "KSwapDoor" backdoor—discovered on compromised Linux servers—revealed malicious binaries masquerading as kernel swap daemons ([kswapd1]), communicating over AES-256-CFB with Diffie-Hellman key exchanges across a peer-to-peer mesh network. This underscored why a CVSS 10.0 vulnerability in a serialization layer requires immediate, unhesitating patching across enterprise infrastructure.
Future Outlook & Actionable Defenses
As server-driven UI frameworks continue to proliferate, engineering organizations must implement a defense-in-depth strategy that extends far beyond relying on framework defaults.
Ranked Defenses for Production Applications
-
Strict Input Validation on Server Actions (Zod / Valibot):
Validate all inputs at the very top of every Server Action before executing any business logic or logging. Destructuring arguments prior to schema validation exposes the application to unvalidated data processing bugs."use server" import z from "zod" const PayloadSchema = z.object( userId: z.string().uuid(), actionType: z.enum(["read", "write"]), ) export async function handleAction(data: unknown) const parsed = PayloadSchema.safeParse(data) if (!parsed.success) return error: "Invalid payload shape" // Proceed safely with parsed.data -
Enforce the
server-onlyPackage:
Prevent sensitive modules containing database credentials or business logic from being imported into Client Components by explicitly initializing"server-only"at the top of utility files. Be wary of barrel files (index.ts) that inadvertently re-export server functions alongside client utilities. -
Hardened CSRF Protections:
Go beyond framework defaults by explicitly configuring strict session cookies (SameSite=Strict,Secure), validating custom CSRF tokens for high-value operations, and ensuring your configuration never explicitly allows'null'origins in server action settings. -
Verify Package Lockfiles:
Ensure React dependencies are strictly locked to patched versions (React 19.0.1+, 19.1.2+, 19.2.1+ for RCE fixes; and subsequent minor bumps for DoS and info-disclosure mitigations). -
Treat the Taint API as a Guardrail:
Leverage React’staintUniqueValueandtaintObjectReferenceto catch accidental data leaks during development, while recognizing that object-reference taint does not survive data transformations or spread operations.
Conclusion
The React Flight protocol is a technological marvel that enables seamless, high-performance server-client streaming. However, as the events surrounding React2Shell demonstrated, moving executable behavior across network boundaries requires absolute vigilance. As the industry moves forward, developers must look beyond trusting the server blindly, adopting cryptographic validation, strict input schemas, and rigorous code auditing to secure the next generation of web applications.
