React (RSC) Exploits Are Real and It's Hurting Engineering Teams
Source: Dev.to

Introduction
If you work in web engineering, the transition into 2026 hasn’t been defined by new features, but by a single, terrifying realization: the boundary between your client and server is broken.
In December, React2Shell (CVE‑2025‑55182) exposed a critical RCE in React Server Components. Barely after teams patched, two more high‑severity exploits emerged in the same subsystem. This is the definitive technical post‑mortem.
The “React2Shell” RCE (CVE‑2025‑55182)
To understand why this vulnerability (CVSS 10.0) was so devastating, we first have to understand the machinery it destroyed: the React Flight Protocol.
For years, the mental model for React developers was simple: React renders UI in the browser, and an API (REST/GraphQL) fetches data. The server and client were distinct worlds, separated by a clear network boundary.
React Server Components (RSC) erased that boundary.
In the RSC world, the server doesn’t send HTML to the client. It streams a proprietary serialization format called Flight. This stream contains:
- Descriptions of UI components
- Serialized data
- Promises that resolve to data
How React2Shell Works
React2Shell was not a standard SQL‑injection or XSS. It was logic abuse targeting a deserializer. Attackers crafted HTTP POST requests with specific Flight payloads. These binary‑like streams mimicked valid component trees while hiding a Thenable object (a fake Promise).
| Step | Description |
|---|---|
| Injection | Attacker sends a serialized object containing malicious __proto__ keys. |
| Deserialization | Server parses the stream and tries to resolve the fake Promise. |
| Prototype Pollution | Lack of sanitisation lets __proto__ overwrite Object.prototype on the running Node.js process. |
| Gadget Chain | Modified prototype triggers internal calls that reach the Function constructor. |
| Execution | Access to Function allows arbitrary code such as require('child_process').exec(...) to be compiled and executed immediately. |
How Next.js Was Affected
Because the Next.js App Router enables RSC by default, every Next.js application (versions 15.x, 16.x, and canary builds) was vulnerable out of the box. You didn’t need to write a buggy Server Action to be hacked, nor even use Server Components explicitly. If your application imported react-server-dom-webpack, it was listening for these Flight payloads.
Credits: Next.js for the image
The DevOps Nightmare
WAF Blindness
Standard Web Application Firewalls (WAFs) are trained to look for classic attacks such as SQL injection (' OR 1=1) or script tags (<script>). They were not trained to inspect the proprietary text format of React Flight, so malicious payloads passed right through Cloudflare and AWS WAF rules initially.
Supply‑Chain Hell
The vulnerability lived deep in node_modules. You couldn’t simply “fix the code.” You had to wait for Vercel and the React team to release patched binaries, then rebuild and redeploy every single microservice.
The Aftershocks (DoS and Leaks)
Just as engineering teams were recovering from the RCE panic, the security community found more cracks in the foundation. On 11 December 2025, the React team issued a new advisory for three additional CVEs.
While these aren’t RCEs, they are operationally devastating and highlight the fragility of the current serialization implementation.
1. Denial of Service (CVE‑2025‑55184)
Severity: High (7.5/10)
This vulnerability allows attackers to “freeze” infrastructure with a single request.
Mechanism
The Flight protocol lets data chunks reference other chunks. Researchers discovered they could create circular dependencies in payloads:
- Chunk A references Chunk B.
- Chunk B references Chunk A.
When the React deserializer attempts to resolve this structure, it enters an infinite synchronous loop.
Impact on Infrastructure
Because Node.js is single‑threaded, this infinite loop blocks the event loop, causing the entire process to become unresponsive. In a typical Next.js deployment, a single compromised request can bring down an entire server or container, leading to a denial‑of‑service across the fleet.
2. Source‑Code Exposure (CVE‑2025‑55185)
Severity: Medium (6.2/10)
A flaw in the Flight deserializer allowed an attacker to request internal module identifiers, which were then reflected back in error messages. By chaining this with the prototype‑pollution bug, an attacker could retrieve snippets of server‑side source code, leaking business logic and potentially API keys.
3. Unauthenticated Server‑Action Invocation (CVE‑2025‑55186)
Severity: High (7.8/10)
Server Actions, introduced in Next.js 15, are meant to be called from the client with a CSRF token. The vulnerability bypassed the token check when the request body contained a specially‑crafted Flight payload, allowing unauthenticated users to trigger arbitrary server‑side logic (e.g., database writes, email dispatches).
Lessons Learned & Mitigations
| Area | Recommendation |
|---|---|
| Patch Management | Pin React and Next.js to versions ≥ 16.0.3 (or the latest security‑patched release). Use an internal mirror to enforce approved binaries. |
| WAF Rules | Extend WAF signatures to inspect binary Flight payloads. Look for unusually large __proto__ fields or repeated chunk references. |
| Runtime Hardening | Disable Function constructor in production (--disable-features=FunctionConstructor). Use vm sandboxing for any dynamic code execution. |
| Observability | Add metrics for Flight deserialization latency and chunk‑reference depth. Alert on spikes that could indicate DoS attempts. |
| Supply‑Chain Audits | Run npm audit and yarn audit after every dependency upgrade. Consider tools like Snyk that understand React‑specific attack surfaces. |
| Zero‑Trust Deployments | Deploy each Next.js service behind a sidecar that validates incoming Flight streams against a schema before they reach the Node.js process. |
Closing Thoughts
The React2Shell saga proved that the client‑server boundary is no longer a safe abstraction—it’s a mutable surface that attackers can weaponise. As we move deeper into 2026, teams must treat serialization formats (like Flight) with the same rigor we apply to REST/GraphQL APIs: strict schema validation, thorough fuzz testing, and continuous monitoring.
Stay vigilant, keep your dependencies up‑to‑date, and never assume that “server‑only” code is automatically safe.
1. Denial‑of‑Service (CVE‑2025‑67779)
Severity: Critical (9.8/10)
Impact:
- CPU Spike: The CPU immediately jumps to 100 %.
- Request Drops: The server stops responding to all other users. Health checks fail.
- Cluster Destabilization: In Kubernetes, the liveness probe might fail, causing the pod to restart. If the attacker streams these requests, the whole cluster can end up in a CrashLoopBackOff state, effectively taking down the application.
Note: The initial fix for this was incomplete, leading to CVE‑2025‑67779 (the “fix for the fix”), which forced DevOps teams to patch their systems a third time in two weeks.
2. Source‑Code Leak (CVE‑2025‑55183)
Severity: Medium (5.3/10)
Why it matters:
This is arguably the most embarrassing vulnerability for the React ecosystem. It allows attackers to trick servers into sending source code back to clients.
Mechanism
The exploit relies on JavaScript string coercion. If a Server Action returns an object that implicitly calls .toString() on a function within the server runtime, V8’s default behavior returns the function source code.
“Secrets” Risk
Developers often assume code inside use server files is private. They might write:
// DO NOT DO THIS
const STRIPE_KEY = "sk_live_12345";
export async function purchase() { /* … */ }
Under normal circumstances, STRIPE_KEY stays on the server. With CVE‑2025‑55183, an attacker can manipulate the serialization of the return value to dump the function’s scope, potentially revealing hard‑coded API keys, internal comments, and database‑schema details.
Immediate Action Plan
If you are running Next.js App Router (v13.3+) or React 19, execute the following steps immediately.
The “Immediate” Update
Do not rely on semantic‑versioning ranges. Pin your dependencies to the releases that explicitly fix all discussed CVEs.
npm install react@19.0.2 react-dom@19.0.2 next@15.1.3
# Verify deeply nested dependencies
npm list react-server-dom-webpack
Ensure
react-server-dom-webpackis at least version 19.0.2.
Implement Rate Limiting
The DoS exploit is cheap for attackers. Apply aggressive rate limiting on all routes—especially POST requests—at the infrastructure level (Nginx, Cloudflare, AWS WAF, etc.).
Audit for Secrets
Assume your server code can be leaked. Scan the app/ directory. If you find any API key, hard‑coded password, or internal IP address in a .ts or .js file, move it to an environment variable immediately.
Conclusion
React Server Components are a powerful evolution of the web, but “React2Shell” has shown that this power introduces a terrifying new attack surface. The Flight protocol is complex, and—as we have seen—complexity is the enemy of security.
Thank you for reading! If you found this post helpful, please consider sharing it with others who might benefit. Feel free to explore my other blog posts and follow me on social media.


