In December 2025, the React ecosystem faced a CVSS 10.0 remote code execution vulnerability that required no authentication, no user interaction, and worked against default Next.js installations with zero custom server code. The vulnerability, dubbed React2Shell, exploited a framework abstraction: the React Flight protocol, designed to transparently transport component trees between server and client, had become the attack surface itself.
What followed was not a single patch cycle but six months of disclosures: four CVEs targeting the same deserialisation code path, a coordinated 13-advisory release from Vercel in May 2026, and confirmed in-the-wild exploitation by state-sponsored groups, cryptojacking operators, and initial access brokers within 48 hours of disclosure. This series maps the crisis across four dimensions — exploit mechanism, vulnerability pattern, trust-model failure, and operational defence — in articles that work together but can also be read independently depending on what you need to know first.
GreyNoise sensors, which monitor internet-wide scanning, recorded over 1.4 million exploitation attempts in a single week. Cloudforce One, observing traffic across Cloudflare‘s global network, counted 582 million hits across eight days at an average rate of 3.49 million per hour. The University of Michigan’s security team recommended sites not behind Cloudflare be taken offline — a telling indicator of real-world severity.
This crisis raises questions that extend beyond version numbers and patch schedules. Can framework abstractions that erase the client/server boundary ever be secured by treating server-side payloads as trusted? And if the default deployment is exploitable by design, where does developer responsibility end and framework vendor accountability begin?
This pillar page maps the full React2Shell crisis across four dimensions — exploit mechanism, vulnerability pattern, trust-model failure, and operational defence — and directs you to the detailed article that answers each question.
In This Series
How React2Shell Turns Framework Abstractions Into Attack Vectors: The exploit chain explained: how a crafted HTTP request becomes shell command execution through the React Flight protocol’s deserialisation process.
The Recurring Deserialisation Vulnerability Pattern in React Server Components: Why four CVEs in the same code path across six months signal a systemic architectural weakness, not isolated bugs.
The React Server Components Trust Model and Why Default Next.js Was Vulnerable: How the implicit trust assumption baked into RSC architecture made default deployments exploitable and what that means for framework security accountability.
React2Shell in the Wild Exploitation Evidence and the Platform Defence Landscape: What attackers are actually doing with React2Shell access and how Cloudflare, Deno Deploy, and other platforms are absorbing the impact.
What Is React2Shell and Why Does It Matter?
React2Shell is the informal name for CVE-2025-55182, a remote code execution vulnerability in React Server Components disclosed on 3 December 2025. It matters because it does not require a developer to make a mistake. The vulnerability exists in the framework’s normal operation. Any Next.js App Router deployment using default settings was exploitable. A single unauthenticated HTTP request containing a crafted Flight protocol payload could execute arbitrary shell commands on the server, with no user interaction and low attack complexity. The CVSS 10.0 score reflects the combination of network attack vector, low complexity, no privileges required, no user interaction, and complete confidentiality, integrity, and availability impact.
The blast radius is defined by framework adoption, not application-specific misconfiguration. Wiz Research found that 39% of cloud environments contained vulnerable instances, and 44% of all environments ran publicly exposed Next.js applications. That is not a long tail of misconfigured apps. That is the default deployment profile.
Unlike Log4Shell (CVE-2021-44228), which required a log message to reach a vulnerable Log4j instance, or Rails YAML deserialisation (CVE-2013-0156), which required an endpoint accepting YAML parameters, React2Shell required only that your application used React Server Components. That is the default for Next.js App Router since version 13.
The vulnerability emerged from a structural property of the React Flight protocol’s trust assumptions: the deserialiser was designed assuming serialised payloads were inherently trustworthy because they originated from the same codebase. No eval(), no child_process.exec(), no insecure configuration flag was involved. When Next.js deployed that deserialiser on the server side and accepted Flight payloads from HTTP requests, the trust boundary collapsed. This is the question the cluster explores: when framework abstractions designed to simplify development become the attack surface, who bears the security burden?
The CVE was reported through Meta‘s bug bounty program on 29 November 2025 by security researcher Lachlan Davidson. The React team turned around a patch in four days. By 5 December, exploitation was detected in the wild. CISA added it to the Known Exploited Vulnerabilities catalog.
Read the full story: How React2Shell Turns Framework Abstractions Into Attack Vectors covers the exploit mechanism in detail, including the thenable abuse and prototype pollution chain that makes this attack class novel.
How Does the React2Shell Exploit Chain Work at a High Level?
The exploit chain has four stages. First, an attacker crafts an HTTP request containing malicious JSX properties embedded in a Flight protocol payload. Second, the server’s Flight deserialiser encounters a “thenable” (a JavaScript object with a .then() method) and eagerly resolves it, executing attacker-controlled code during deserialisation. Third, the attacker uses prototype pollution to inject properties onto Object.prototype that the framework later interprets as executable references. Fourth, the corrupted prototype chain causes the server to evaluate the attacker’s expressions, resulting in shell command execution. The entire chain executes before any application-level authentication, authorisation, or validation occurs.
React Server Components use the Flight protocol to serialise component trees — JSX, props, state, and module references — into a binary-like format that travels between server and client. When a Next.js App Router page renders, the server serialises the component tree and sends it to the client. When the client navigates or submits a server action, it sends a Flight payload back. The server-side deserialiser that reconstructs these payloads is the attack surface. Here is the insight that makes this vulnerability class different: the deserialiser runs before any framework middleware, authentication layer, or application logic. Malicious payloads execute in a pre-authorisation context. How the trust model enabled this is analysed in depth in our examination of why default Next.js was vulnerable.
In JavaScript, a “thenable” is any object with a .then() method. The language’s await keyword automatically invokes it. The Flight deserialiser uses await to resolve component data, so when an attacker supplies a thenable whose .then() callback contains malicious code, the deserialiser unwittingly executes it. Meanwhile, the attacker uses __proto__ keys in the serialised payload to modify Object.prototype globally on the server process. When the framework later checks a polluted property expecting a benign value, it finds the attacker’s injected function reference instead.
The combination — thenable auto-invocation plus prototype chain corruption — transforms data deserialisation into code execution without any explicit eval() or exec() call in user code. The attacker does not exploit application logic or developer error. They exploit the framework’s design. The Flight protocol’s chunk resolution mechanics ($id references, $@ raw references, $B blob references) were designed for server-to-client data marshalling, not for adversarial input.
The vulnerability resides in React’s reviveModel function within ReactFlightReplyServer.js. When traversing chunks during reference resolution, React failed to verify whether a requested key was an own property of the object versus an inherited prototype property. In JavaScript, obj[key] can return values inherited from Object.prototype, not just the object’s own properties. The vulnerable code used this approach, asking the untrusted object itself whether a property existed anywhere in its prototype chain rather than checking only its own properties. Trend Micro’s analysis described the effect plainly: “much like asking a burglar if they’re supposed to be in your house.”
The complete walkthrough: How React2Shell Turns Framework Abstractions Into Attack Vectors walks through every stage of the exploit chain with the technical detail you need before evaluating risk or defences.
What Is the React Flight Protocol and Why Was It Vulnerable?
The React Flight protocol is the serialisation format and transport mechanism that makes React Server Components possible. It streams serialised component trees, props, state, and module references between server and client. It was vulnerable because it was designed for a trusted communication channel. The original design space assumed Flight payloads originated from a React server rendering its own component tree, not from HTTP request bodies. When Next.js deployed the same deserialiser on the server side to handle client-submitted payloads (for server actions, form submissions, and client navigations), it inherited the “payloads are trusted” assumption without adding an untrusted-input validation boundary.
Unlike a REST API that returns structured JSON data, or traditional SSR that renders HTML templates, the Flight protocol transmits a serialised representation of the entire component tree, including which components to render, their props, their internal state, and references to server-side module code. That richness is the protocol’s strength: it enables the seamless server/client component model that makes RSC architecturally compelling. But that same richness — object graphs, module references, thenables, blob handles — is also what makes it an attack surface. Every feature that enables expressive component serialisation is a potential exploitation primitive.
The protocol was developed within Meta for internal use, where server-to-client communication was inherently trusted. When the protocol was open-sourced and adopted by Next.js for public-facing deployments, the trust assumption travelled with it. The server-side deserialiser was not architected for adversarial input. It lacked strict type validation, cycle detection, property allow-listing, and input sanitisation. These are not implementation oversights. They reflect a design philosophy that treated deserialisation as an internal data-marshalling operation rather than a security boundary.
This is the tension at the heart of the crisis. The Flight protocol needs to be expressive enough to represent arbitrary component trees, but expressive serialisation formats are dangerous when exposed to untrusted input. This is the same tension that produced vulnerabilities in Java’s ObjectInputStream, PHP’s unserialize(), and Python’s pickle. The difference is that those deserialisation functions required an explicit developer choice to use them on untrusted data — a well-understood antipattern. The Flight protocol deserialises by default, as part of normal framework operation, and the developer never explicitly opts into accepting untrusted input.
Deeper context: How React2Shell Turns Framework Abstractions Into Attack Vectors maps the Flight protocol’s technical surface. The React Server Components Trust Model and Why Default Next.js Was Vulnerable analyses the trust-model implications.
What Makes React2Shell Different from Other Web Framework Vulnerabilities?
React2Shell differs from historical framework vulnerabilities in three ways. First, it does not require developer error. The attack surface exists in default installations with zero custom code. Second, the vulnerability is architectural rather than configurational: the Flight protocol’s deserialiser is invoked by normal framework operation, not by an explicit developer choice to handle untrusted input. Third, the exploit executes before authentication, authorisation, or application-level validation. A malicious payload reaches the deserialiser before any middleware or security layer can inspect it. This combination makes React2Shell closer to a protocol-level vulnerability than a typical application-level CVE.
Benchmark it against the vulnerabilities you are most likely using as mental models. Log4Shell (CVE-2021-44228) required a crafted string to reach a Log4j logging call. Configuration-dependent and mitigable at the logging layer. Rails YAML deserialisation (CVE-2013-0156) required an endpoint accepting YAML parameters. Opt-in by application design. PHP unserialize() vulnerabilities required a developer to call unserialize() on user input. A well-known antipattern with established defences.
React2Shell requires none of these conditions. If your application uses React Server Components, the deserialiser is active. There is no configuration flag to disable it, no function call to audit for, no middleware position where you can insert a validation layer before the deserialiser runs. This is what security researchers mean when they call it an “architectural” vulnerability. The attack surface is baked into the framework’s design, not introduced by how you use it.
The blast-radius comparison is instructive. Log4Shell’s blast radius was large because Log4j was embedded in thousands of Java applications across every industry, but each affected application had to log a user-controlled string. React2Shell’s blast radius is defined by a single architectural choice: whether the application uses React Server Components. That choice is the default for Next.js App Router, the most popular React framework. The result is a vulnerability class where the exposed population is essentially every Next.js App Router deployment that has not patched.
React2Shell also represents a new category of framework vulnerability: the abstraction-attack. Most framework vulnerabilities exploit implementation bugs — a missing bounds check, an incorrect permission check, an injection vector in a template engine. React2Shell exploits a design decision: the assumption that serialised component payloads are trustworthy. That assumption was reasonable when the Flight protocol operated within Meta’s internal infrastructure, where server-to-client communication was inherently trusted. It became dangerous when Next.js deployed the same deserialiser to handle HTTP request bodies from any client on the public internet. This category of vulnerability is likely to recur as more frameworks adopt serialisation-based protocols that blur the client/server boundary.
The full comparison: How React2Shell Turns Framework Abstractions Into Attack Vectors provides the detailed comparative analysis against Log4Shell, Rails YAML, and other benchmark vulnerabilities.
What Is the Broader React Server Components Security Crisis Beyond the Initial CVE?
If React2Shell were a single vulnerability, it would still be significant. But it was not. Across six months, four distinct CVEs targeted the same RSC deserialisation code path: the original RCE (CVE-2025-55182), a separate protocol-level flaw (CVE-2025-66478, also CVSS 10.0), a cyclic deserialisation denial-of-service (CVE-2026-23869, CVSS 7.5), and a further deserialisation DoS (CVE-2026-23870). By May 2026, Vercel’s coordinated security release patched 13 advisories in a single batch, covering middleware bypass, SSRF, cache poisoning, and XSS alongside the RSC-specific flaws. The crisis scope reveals that the attack surface is wider than any single CVE: it encompasses the Flight protocol, the surrounding server infrastructure, and the dependency chain connecting them.
CVE-2025-66478 demonstrated a separate flaw in the RSC protocol itself — not just an implementation bug, but a design-level weakness in how the protocol handled certain payload structures. CVE-2026-23869 showed that the deserialiser lacked cycle detection: an attacker could crash the server by sending a Flight payload containing circular object references, triggering infinite recursion during deserialisation. CVE-2026-23870 continued the pattern even after the cyclic-DoS patch, revealing that each fix addressed one vector without closing the systemic weakness.
And then there were the others. CVE-2025-55184 exploited recursive deserialisation of Promises within the Flight Protocol, inducing Microtask Queue Starvation that rendered the server process comatose while keeping TCP ports open. Its fix was incomplete (CVE-2025-67779), requiring yet another upgrade cycle. CVE-2025-55183 allowed source code exposure through Server Function argument coercion. The May 2026 Vercel batch expanded the scope further: SSRF through the RSC rendering pipeline, cache poisoning through manipulated Flight responses, and XSS through the boundary where serialised components meet HTML rendering.
These are symptoms of the same underlying pattern: the Flight protocol deserialiser and its surrounding server infrastructure were under-explored at release, each patch revealed adjacent attack surface, and the complexity of the deserialisation codebase made root-cause fixes harder than targeted patches.
The advisory sequence — December 2025, January 2026, May 2026 — suggests three interpretive possibilities that are all likely true: independent researchers found different vectors on different timelines, each patch revealed adjacent attack surface to follow-up researchers, and the complexity of the deserialisation codebase meant root-cause fixes were harder than targeted patches. The pattern itself is the evidence: the attack surface was under-explored at release, and hardening it is an ongoing process, not a one-time fix.
Sonatype’s security research team put it plainly: “Don’t treat React2Shell, 55183, 55184, and 67779 as four surprises. Treat them as four early members of a React RSC vulnerability family you’ll be living with for a while.”
The full crisis scope: The Recurring Deserialisation Vulnerability Pattern in React Server Components catalogues every CVE, the version sprawl problem, and the architectural diagnosis.
Why Did the React Team and Vercel Issue Multiple Waves of Advisories Within Months?
The advisory cadence reflects three converging factors. First, the Flight protocol’s attack surface was larger than the initial disclosure captured. Independent researchers found different exploitation paths (DoS, source-code leaking, protocol-level RCE) on separate timelines. Second, each targeted patch revealed adjacent weaknesses to researchers who studied the fix commits. Third, the deserialisation codebase’s complexity made root-cause fixes harder than incremental patches. Each CVE addressed one exploitation vector without redesigning the trust boundary. The coordinated 13-advisory May 2026 release from Vercel was an acknowledgement that reactive patching was not closing the surface fast enough.
Unlike a simple input validation bug — where the fix is a clear bounds check and the attack surface is closed — the Flight protocol deserialiser handles a rich object graph with multiple resolution paths, reference types, and execution contexts. When researchers studied the patch for CVE-2025-55182, they identified the thenable resolution path. When that path was hardened, they identified cyclic reference handling. Each fix narrowed the surface but did not eliminate it because the deserialiser’s design — eagerly resolving structured data into executable objects — remained intact.
The version sprawl problem was significant. Different advisory waves covered different React version lines (19.0.x, 19.1.x, 19.2.x) and different Next.js release channels (14.x, 15.x, 16.x, canary). The May 2026 coordinated release required upgrading across multiple packages — react, react-dom, react-server-dom-webpack, next — rather than a single version bump. For organisations with complex dependency trees, this created a multi-stage patching process where partial upgrades could leave some attack vectors closed and others open. Vercel shipped an automated patching tool (npx fix-react2shell-next) to help operators navigate the complexity.
This is why the advisory pattern matters in practice: it is not just about whether you patched, but whether you can be confident you patched everything.
The advisory pattern analysed: The Recurring Deserialisation Vulnerability Pattern in React Server Components provides the complete version matrix and patch sequencing. The React Server Components Trust Model and Why Default Next.js Was Vulnerable addresses the architectural root cause.
Why Does React2Shell Work on Default Next.js Configurations with No Custom Server Code?
React2Shell works on default Next.js installations because the App Router enables React Server Components by default. Any app/ directory with page.tsx files automatically participates in the Flight protocol. The framework serialises component trees, sends them to clients, and accepts Flight payloads back via server actions and client navigations. The server-side deserialiser that processes these incoming payloads is active by default, with no configuration flag to disable it. The attack surface is present simply by using Next.js as documented.
When you run create-next-app and choose the App Router, your application immediately has server components, server actions, and Flight protocol endpoints. The /_rsc endpoint — which handles client navigations and server action submissions — accepts Flight protocol payloads from any HTTP client. The framework does not ask you whether you want this. It is the architectural foundation of the App Router. The Flight deserialiser that processes these payloads runs in the same Node.js process as your application code, with the same filesystem access, environment variables, and network privileges. This is not a misconfiguration. It is the design.
Most developers understand that user input is untrusted and must be validated — form fields, URL parameters, API request bodies. But a serialised component tree does not feel like user input. It feels like framework internals. The Flight payload format is not documented as a public API surface; it is generated by the framework’s own serialisation code. This creates a dangerous trust assumption: if the framework generates it, and the framework receives it back, it must be trusted. The React2Shell exploit demonstrates that this assumption is false. Any HTTP client can craft a Flight payload, and the deserialiser will process it with the same trust it grants to payloads generated by its own serialiser.
The accountability question is unavoidable. When a framework’s default deployment is exploitable, the traditional security responsibility model — developers secure their code, framework vendors secure the framework — breaks down. The developer did not introduce the vulnerability; the framework’s architectural decision did. But the developer’s server is the one that gets compromised. This tension — between framework design authority and operational security responsibility — is the question the trust-model article investigates.
Next.js 13.x, Next.js 14.x stable, Pages Router applications, and the Edge Runtime are not affected. The vulnerability requires the App Router specifically. This architectural distinction is important when you are evaluating your own exposure surface.
The trust-model analysis: The React Server Components Trust Model and Why Default Next.js Was Vulnerable explores the accountability framework and vendor security posture questions. How React2Shell Turns Framework Abstractions Into Attack Vectors explains the exploit mechanism that default configurations enable.
How Does the RSC Trust Model Compare to Traditional Server-Side Rendering Security?
Traditional server-side rendering (SSR) has a clear security boundary: the server renders trusted templates, and untrusted user input passes through explicit escaping and validation layers before reaching the rendering engine. The attack surface is the template engine’s handling of user-controlled data — a well-understood and actively managed boundary. React Server Components invert this. The user input is the entire serialised component tree — a rich object graph containing module references, thenables, and prototype chains — and the framework processes it as trusted data before any application-level validation can occur. The attack surface is the deserialiser itself, not the rendering output.
In a traditional Express with EJS or Rails ERB application, the rendering pipeline looks like this: HTTP request, routing, controller logic, template rendering with escaped user inputs, HTML response. The user’s data flows through explicit validation and escaping checkpoints. The template engine receives pre-sanitised inputs. Even if a developer makes an escaping error, the vulnerability is typically cross-site scripting — client-side impact — rather than remote code execution.
In Next.js App Router with server components, the pipeline is: HTTP request, Flight payload deserialisation, component rendering, serialised response. The key difference is that deserialisation happens first, before any routing, middleware, or application logic. A malicious Flight payload reaches the deserialiser intact, and the deserialiser executes logic — resolving thenables, traversing prototypes, reconstructing object graphs — based on attacker-controlled data. The attack surface is broad. Every feature the deserialiser supports is a potential exploitation primitive.
RSC’s architectural difference — deserialise first, validate later — makes its trust model more permissive than alternatives.
REST APIs make this boundary even more explicit. Every request component is untrusted: headers, query parameters, body, content type. Validation is explicit, programmable, and positioned before business logic. RSC treats the Flight payload as an internal data structure and processes it before validation can occur. JSON is “dumb” in exactly the right way: there is no deserialisation of execution contexts, no automatic invocation of client-specified code paths, no blurred boundaries between data and code. The Flight protocol needed to be smarter than JSON, capable of serialising promises, closures, and complex object graphs. That meant it needed to be more complex, more powerful, and more dangerous.
The architectural question is whether this difference is a temporary maturity gap that better input validation will close, or a property of serialisation-based protocols that will always create a pre-validation attack surface. The React2Shell cluster evidence — four CVEs in six months, each exploiting different deserialisation paths — suggests the answer is not simple.
The trust-model comparison: The React Server Components Trust Model and Why Default Next.js Was Vulnerable provides the full analysis of how RSC’s architectural choices compare to SSR and REST security models.
Is the RSC Security Model Fundamentally Flawed, or Is This a Maturity Problem?
There are two defensible interpretations, and the React2Shell evidence supports both. The maturity argument: the Flight protocol is a young serialisation format compared to JSON or Protocol Buffers. Its deserialiser was not battle-tested against adversarial inputs because its original design space assumed trusted server-to-client communication. The four CVEs represent growing pains — a deserialiser maturing under fire.
The fundamental argument: any serialisation format rich enough to represent executable code patterns — thenables, prototype chains, cyclic references — will always have an attack surface when exposed to untrusted input, regardless of maturity. Each new deserialiser feature is a new potential exploitation primitive.
The Flight protocol needs to be expressive: it serialises component trees with module references, async values (thenables), object graphs with shared references, and blob handles. Each of these features maps to a well-known attack primitive. Module references enable code execution through the module loader. Thenables enable auto-invocation through JavaScript’s await semantics. Shared references — the $id system — enable prototype chain traversal. Blob handles enable resource confusion. No amount of input validation can eliminate these primitives without also eliminating the features that make the protocol useful.
If the protocol needs to be this expressive, and expressiveness creates attack surface, then the security problem is structural. It can be managed through defence-in-depth — sandboxing, capability dropping, WAF inspection — but not solved through deserialiser hardening alone. The recurring vulnerability pattern documented in our analysis of the deserialisation crisis reinforces this: each patch closed one vector, but the structural tension between expressiveness and safety kept producing new ones.
The React team’s 4-day turnaround on the initial patch is impressive. The fact that researchers kept finding new vectors in the same code path for six months afterwards is telling. The pragmatic question is not “is RSC secure?” — it is “is the residual risk acceptable for my deployment’s threat model, given the current state of hardening and the available platform-level defences?” The trust-model article explores this through the lens of vendor accountability and adoption risk assessment. The exploitation article provides the operational evidence to inform your evaluation.
Make your own assessment: The React Server Components Trust Model and Why Default Next.js Was Vulnerable presents both arguments in full. React2Shell in the Wild Exploitation Evidence and the Platform Defence Landscape provides the real-world data.
How Are Attackers Actually Exploiting React2Shell in the Wild?
Exploitation began within 48 hours of the 3 December 2025 disclosure. GreyNoise telemetry recorded over 1.4 million exploitation attempts within seven days. Cloudforce One observed 582 million hits across eight days at an average rate of 3.49 million per hour. Two IPs alone generated 56% of all observed exploitation traffic in one week. The initial wave was dominated by mass scanning and opportunistic exploitation, but within the first week, evidence of targeted post-exploitation activity emerged from multiple threat hunting teams.
The attacker profile spans four categories. China-nexus groups — CL-STA-1015 and Earth Lamia — deploying espionage backdoors. DPRK-linked actors (UNC5342, also known as Contagious Interview) using EtherRAT for cryptocurrency theft, with C2 resolution through Ethereum smart contracts. Cryptojacking operators deploying XMRig miners via the C3Pool Monero mining pool. And initial access brokers deploying SNOWLIGHT, VShell, and KSwapDoor for onward access sales.
The post-exploitation malware catalogue is diverse. Huntress observed PeerBlight — a Linux backdoor — CowTunnel — a reverse proxy tunnel — ZinFoq — a Go-based implant — and a Kaiji botnet variant. Google’s Threat Intelligence Group identified MINOCAT tunneler, HISONIC backdoor, and COMPOOD backdoor. ThreatLocker even observed exploitation against IIS servers on Windows, with attackers deploying XMRig via PowerShell after initially attempting Linux commands.
A Metasploit module and Nuclei template were publicly available, lowering the barrier to exploitation. Automated scanning used identifiable User-Agents like “Nuclei – CVE-2025-55182” and “React2ShellScanner/1.0.0.” The 48-hour gap between disclosure and active exploitation reflects the availability of public tooling and the fact that attackers understood the Flight deserialiser was an architectural weak point, not an application-specific bug. Understanding the exploit mechanism itself clarifies why attackers moved so quickly: the attack surface was universal, not application-specific.
The exploitation data validates the trust-model analysis: attackers exploited it at internet scale because they understood it was a framework-level vulnerability, not a developer mistake. But the data also shows that platform-level defences — Cloudflare’s automatic WAF rules, Deno’s runtime isolation — absorbed a significant portion of the impact. The question for your organisation is not just “are we patched?” but “what is our exposure surface, and which defensive layers sit between the internet and our RSC endpoints?”
The complete exploitation picture: React2Shell in the Wild Exploitation Evidence and the Platform Defence Landscape covers the full threat actor landscape, post-exploitation payload catalogue, and IoC categories.
How Do Different Hosting Platforms Defend Against React2Shell Exploitation?
Platform defences fall into two strategies. Cloudflare deployed WAF rules automatically for all users — including Free tier — within hours of disclosure, inspecting HTTP traffic for malicious Flight payload patterns before they reach the origin server. The Cloudflare Workers runtime adds V8 isolate-based sandboxing that limits blast radius even if exploitation succeeds. Deno Deploy takes a different approach: its permission-based runtime denies filesystem, network, and subprocess access by default, so even if a malicious Flight payload is deserialised, post-exploitation capabilities are curtailed at the runtime level. Vercel’s response focused on framework-level patching at the source — the coordinated 13-advisory May 2026 release addressed deserialisation vulnerabilities directly.
Cloudflare’s dual-layer defence is worth understanding. The WAF layer inspects HTTP traffic at the network edge, applying signatures that detect malicious Flight payload patterns — __proto__ traversal attempts, thenable injection, chunk reference manipulation. Because Cloudflare manages these rules centrally, users received protection without any configuration changes. The Workers runtime layer provides process-level isolation: each worker runs in a separate V8 isolate with no shared memory, so a compromised worker cannot access other tenants’ data or the host system. Cloudflare describes React-based applications deployed on Workers as “inherently immune.”
There is a limitation to keep in mind: WAF signature-based detection can be bypassed through payload obfuscation. The 703-byte to 375MB payload size range observed in the wild suggests attackers are actively probing signature boundaries. Effective WAF rules need to block more than just __proto__ — the maple3142 exploit variant does not use __proto__ at all. They need to inspect $@ chunk references, resolved_model strings, constructor:constructor patterns, and _formData.get patterns.
Deno Deploy’s runtime-isolation approach is different from WAF inspection. Rather than trying to detect malicious payloads, Deno makes the post-exploitation environment incapable of executing the attacker’s objectives. A React2Shell exploit that deserialises a malicious payload and attempts to spawn a shell, write to disk, or establish an outbound connection hits the permission boundary before reaching the host.
The platform comparison is a trade-off analysis, not a winner-takes-all. Cloudflare’s approach — automatic WAF plus sandbox isolation — provides the broadest coverage because it protects all Cloudflare-proxied applications regardless of where the origin server is hosted. Deno’s approach — runtime-level capability denial — provides the strongest post-exploitation containment but only for Deno-deployed applications. Vercel’s approach — framework-level patches at the source — eliminates the vulnerability class but requires applications to upgrade, and the multi-wave advisory pattern suggests patching is an ongoing process, not a one-time event.
Microsoft published WAF rule guidance for Azure Web Application Firewall. CrowdSec released a dedicated virtual patching detection rule within hours of disclosure plus a React2Shell IP blocklist. Fortinet deployed IPS signatures (2066027, 2066028). The optimal strategy combines all three layers: deploy behind a WAF that inspects Flight payloads, run on a runtime that limits post-exploitation capabilities, and keep the framework patched.
The platform defence comparison: React2Shell in the Wild Exploitation Evidence and the Platform Defence Landscape provides the complete WAF comparison, runtime isolation analysis, and defence verification dimensions.
What Questions Should You Ask Before Adopting React Server Components?
Five questions should guide your evaluation. First, what is your framework vendor’s current deserialiser input validation boundary — does it still assume trusted payloads, or has the Flight protocol been redesigned with an explicit untrusted-input posture? Second, what is the vendor’s security advisory process and typical patch latency for RSC vulnerabilities? Third, how does your deployment platform isolate RSC execution from the host environment — V8 isolate sandboxing, permission-based runtimes, or process-level containment? Fourth, what is your ability to deploy WAF rules that inspect Flight protocol payloads — does your CDN or API gateway understand the binary Flight format? Fifth, what is your fallback strategy if RSC adoption introduces unacceptable residual risk — can you migrate back to Pages Router or a traditional SSR architecture without a complete rewrite?
Each question maps to a dimension of the crisis that was exposed during the December 2025 to June 2026 period: the original Flight protocol’s trust assumptions, the multi-wave advisory pattern and version sprawl problem, the observed post-exploitation payloads and the platforms that blocked them, the WAF bypass techniques observed in the wild, and the reality that some organisations may conclude the residual risk is unacceptable for their threat model.
These questions are not about whether React Server Components are “safe” or “unsafe.” They are about whether the residual risk is acceptable given your threat model, deployment architecture, and operational security capability. A financial services organisation with regulatory requirements for data isolation may reach a different conclusion than a content website. An organisation already behind Cloudflare with managed WAF rules may have different residual risk than one running on bare metal.
The framework ecosystem is in active motion. The React team and Vercel have demonstrated rapid-response capability. Platform vendors have absorbed significant defensive burden on behalf of their users. The vulnerability cluster has driven deserialiser hardening that will benefit all future RSC deployments. But the structural questions — whether expressive serialisation formats can ever be secured against adversarial input without sacrificing the expressiveness that makes them useful — remain open. Your adoption decision should account for both the current state and the trajectory.
The evaluative framework: The React Server Components Trust Model and Why Default Next.js Was Vulnerable provides the full vendor-question analysis. React2Shell in the Wild Exploitation Evidence and the Platform Defence Landscape provides the operational context to ground your evaluation.
Resource Hub: React2Shell Deep Dives
Understanding the Exploit Mechanism
How React2Shell Turns Framework Abstractions Into Attack Vectors: The complete exploit chain: how a crafted HTTP request traverses the Flight protocol’s deserialisation process, abuses thenable auto-invocation and prototype pollution, and achieves shell command execution without exploiting developer-introduced code. Start here if you need the technical mechanism before evaluating risk or defences.
Analysing the Architectural Pattern
The Recurring Deserialisation Vulnerability Pattern in React Server Components: Why four CVEs in the same deserialisation code path across six months signal a systemic architectural weakness rather than isolated implementation bugs. Covers the full vulnerability cluster (CVE-2025-66478, CVE-2026-23869, CVE-2026-23870) and the multi-wave advisory pattern that revealed the attack surface’s breadth.
The React Server Components Trust Model and Why Default Next.js Was Vulnerable: The architectural analysis of why React2Shell worked on default installations: how the Flight protocol’s trusted-payload assumption, combined with Next.js App Router’s default RSC enablement, created an exploitable-by-design deployment profile. Includes the accountability framework for evaluating framework vendor security posture.
Responding to the Operational Reality
React2Shell in the Wild Exploitation Evidence and the Platform Defence Landscape: What attackers are actually doing with React2Shell access, from XMRig cryptomining to state-sponsored espionage backdoors, and how Cloudflare, Deno Deploy, and other platforms are absorbing the impact through WAF detection and runtime isolation. Read this if you are in an operational security or platform engineering role.
Suggested reading order: Start with the exploit mechanism article (ART001) for technical grounding, then the vulnerability pattern article (ART002) for crisis scope, then the trust-model article (ART003) for architectural analysis, and finally the exploitation and defence article (ART004) for operational response. If you are evaluating immediate risk to your own deployments, the trust-model and operational articles (ART003 and ART004) are the most directly actionable.
Frequently Asked Questions
What is CVE-2025-66478 and how does it relate to React2Shell?
CVE-2025-66478 was the original Next.js-specific CVE identifier for the React2Shell vulnerability, issued alongside CVE-2025-55182 (the React-level identifier). NIST subsequently rejected CVE-2025-66478 as a duplicate. If you encounter references to the Next.js CVE number in older advisories or scanner output, it refers to the same vulnerability as React2Shell. CVE-2025-55182 is the authoritative identifier. Both React and Next.js patches are required for complete remediation.
What versions of React and Next.js are vulnerable?
React versions 19.0 through 19.2.0, and Next.js versions 14.x (App Router), 15.x, and 16.x prior to their respective patched releases, are vulnerable. The specific patched versions depend on your release line: React 19.0.1, 19.1.2, and 19.2.1; Next.js 14.2.35, 15.0.5+, and 16.0.7+. The May 2026 coordinated Vercel release added additional patches across multiple packages. Consult the official React and Next.js security advisories for version-specific guidance. The Recurring Deserialisation Vulnerability Pattern in React Server Components provides the complete version matrix.
How is React2Shell different from Log4Shell?
Both are remote code execution vulnerabilities exploiting unsafe deserialisation or log-injection in ubiquitous frameworks via single unauthenticated HTTP requests. The key difference is architectural: Log4Shell required a crafted string to reach a Log4j logging call — configuration-dependent — while React2Shell exploits a framework deserialisation path that is active by default in all Next.js App Router deployments. Log4Shell could be mitigated at the logging configuration layer; React2Shell’s deserialiser runs before any middleware or application logic can inspect the payload. How React2Shell Turns Framework Abstractions Into Attack Vectors provides the detailed comparative analysis.
Is Server-Side Rendering (SSR) also vulnerable to React2Shell?
No. Server-Side Rendering — where React components render to HTML on the server and the client hydrates the resulting markup — does not use the Flight protocol and does not expose the RSC deserialisation attack surface. SSR alone does not create React2Shell exposure. The vulnerability requires React Server Components, which are enabled by default in Next.js App Router but not in Pages Router or traditional SSR setups. The React Server Components Trust Model and Why Default Next.js Was Vulnerable addresses the SSR vs RSC distinction in detail.
What are the signs that a React2Shell compromise has already occurred?
Indicators cluster around unusual process behaviour: Node.js processes spawning unexpected child processes (especially sh, bash, curl, wget); outbound network connections from the RSC rendering process to unknown IP addresses or cryptocurrency mining pools; anomalous CPU utilisation patterns consistent with cryptomining; and Flight protocol request bodies containing __proto__, constructor, or .then patterns in positions inconsistent with normal RSC traffic. These are observable artefact categories rather than definitive indicators. Their presence warrants investigation, but their absence does not guarantee safety. React2Shell in the Wild Exploitation Evidence and the Platform Defence Landscape covers IoC categories in depth.
Should I migrate away from Next.js App Router to Pages Router?
This is a risk-acceptance decision, not a technical one. Pages Router does not use React Server Components and is not affected by React2Shell, so migrating eliminates this specific attack surface. But migration from App Router to Pages Router is architecturally significant. It may require restructuring your component tree, abandoning server actions, and losing performance benefits of RSC streaming. The decision depends on your threat model, your deployment’s exposure surface — are you behind a WAF? on an isolated runtime? — your organisation’s patching velocity, and your tolerance for architectural churn. The React Server Components Trust Model and Why Default Next.js Was Vulnerable provides the evaluative framework.
How do WAF rules actually detect React2Shell payloads?
WAF detection faces a challenge: Flight protocol payloads are binary-like structured data, not human-readable HTTP parameters. Traditional WAF rules that inspect URL query strings or form-encoded bodies will not see the exploit. Effective detection requires parsing the Flight protocol format to identify malicious patterns — __proto__ property traversal, thenable injection via .then method references, chunk reference manipulation via $id and $@ syntax, and unusual status field values. Cloudflare’s managed rules perform this parsing automatically. Payload obfuscation — varying chunk sizes, encoding variations, and reference indirection — remains an active cat-and-mouse game. React2Shell in the Wild Exploitation Evidence and the Platform Defence Landscape provides the complete WAF comparison.
Is the React ecosystem likely to see more vulnerabilities of this class?
The evidence suggests yes, for two reasons. First, the Flight protocol’s expressiveness — component tree serialisation with module references, async resolution, and shared object graphs — creates a rich attack surface that is difficult to exhaustively validate. Second, the framework trend toward serialisation-based client/server protocols — not just React, similar patterns are emerging in other frameworks — means the class of “abstraction-as-attack-surface” vulnerabilities is likely to grow. The React ecosystem’s rapid hardening pace is encouraging, but the structural tension between protocol expressiveness and adversarial safety is not unique to React and is not fully resolved by any current approach. The Recurring Deserialisation Vulnerability Pattern in React Server Components covers the pattern analysis. The React Server Components Trust Model and Why Default Next.js Was Vulnerable covers the architectural implications.
Where to Go from Here
The React2Shell crisis tests whether framework abstractions that erase the client/server boundary can ever be secured by treating server-side payloads as trusted. The operational evidence shows the ecosystem is absorbing the impact through platform-layer defences: Cloudflare’s automatic WAF rules, Deno Deploy’s runtime isolation, and Vercel’s coordinated patching. But the trust-model analysis suggests the structural questions remain open.
React maintained a clean security record over 13 years. One minor XSS vulnerability (CVSS 6.1) in 2018. Then React2Shell landed, and four more CVEs followed in the same code path within six months. That pattern is not a coincidence. It is what happens when a protocol designed for internal trusted communication gets deployed on the public internet without a security boundary redesign.
The good news: the framework ecosystem is responding fast. Platform vendors are absorbing defensive burden on behalf of users who never had to configure a thing. The deserialiser hardening driven by this vulnerability cluster will benefit every future RSC deployment.
The open question: is the residual risk acceptable for your deployment, given your threat model and the platform defences available to you? That is not a question anyone can answer for you. But the articles in this cluster give you the evidence to answer it yourself.
If you need the exploit mechanism explained, start with How React2Shell Turns Framework Abstractions Into Attack Vectors. If you are evaluating architectural risk across your own deployments, read The Recurring Deserialisation Vulnerability Pattern in React Server Components and The React Server Components Trust Model and Why Default Next.js Was Vulnerable. If you are in an operational security or platform engineering role, go directly to React2Shell in the Wild Exploitation Evidence and the Platform Defence Landscape.