React2Shell is a real, high‑severity remote code execution issue in React Server Components (CVE‑2025‑55182) with confirmed exploitation in the wild and a downstream advisory for Next.js (CVE‑2025‑66478). If you run App Router or any RSC‑aware stack, treat this as an incident, not a routine update. Below is a pragmatic, 14‑day plan to patch React and Next.js, harden your edge, and generate proof that satisfies security, customers, and auditors.
What changed—and when
Here’s the thing: dates matter when leadership asks, “When did we know, and what did we do?” On December 3, 2025, the React team publicly disclosed a CVSS 10.0 RCE in React Server Components and shipped patches to npm (19.0.1, 19.1.2, 19.2.1). Next.js followed with its own advisory (CVE‑2025‑66478) naming affected App Router lines and publishing fixed releases across 15.x and 16.x. Two days later, on December 5, 2025, an unrelated but telling moment hit the industry: a major edge provider briefly went down while rolling protective changes for the same React issue—reminding everyone that rushing WAF updates can backfire. On December 11, 2025, React issued two additional, non‑RCE fixes (DoS and source exposure), with backports to 19.0.2, 19.1.3, and 19.2.2. Translation: the patch train kept moving for over a week. Your rollout plan should too.
Who’s actually vulnerable?
Focus on server‑rendered React using the RSC “Flight” protocol. The affected packages are react-server-dom-webpack, react-server-dom-parcel, and react-server-dom-turbopack in versions 19.0.0, 19.1.0, 19.1.1, and 19.2.0. Patches landed as 19.0.1/19.1.2/19.2.1, then again to address follow‑ups in 19.0.2/19.1.3/19.2.2. On the framework side, Next.js App Router builds on RSC and was impacted; stable patched variants were released across 15.x and 16.x. Pages Router and Edge Runtime aren’t in scope for the core RCE, but don’t assume that means you’re safe—shared middleware, SSR endpoints, or third‑party plugins can create unexpected exposure. Verify your dependency tree and deployment topology.
The React2Shell 14‑day patch‑and‑proof plan
This plan assumes you operate at least one RSC‑capable app and want zero‑to‑low downtime. Adjust by environment size, but try to keep the cadence—speed is part of the mitigation.
Day 0–1: Declare the incident, freeze risky deploys, inventory
Call it what it is: a security incident. Pause feature deploys that touch server logic, configuration, or edge policies. Build a fast SBOM and inventory everywhere RSC can run.
Practical checks:
- Code:
npm ls react-server-dom-webpack react-server-dom-parcel react-server-dom-turbopack. If any show 19.0.0/19.1.0/19.1.1/19.2.0, you’re vulnerable. - Frameworks: Grep for App Router in Next.js (
app/directory) and checkpackage.jsonfornext@15ornext@16. - Plugins: Vite RSC, Parcel RSC, Waku, Redwood SDK previews—upgrade along with React.
- Topology: Identify public endpoints that deserialize RSC traffic. Map which edges, proxies, or serverless layers terminate requests.
Document owners per system. You’ll need names and timestamps when you present to execs and customers.
Day 1–2: Patch React and Next.js in dev/stage
Upgrade React RSC packages to patched lines and pin them. For Next.js, move to the closest patched point release in your major/minor line.
Suggested commands:
# React core + RSC packages (choose your minor line)
npm install [email protected] [email protected] [email protected]
# or 19.1.3 / 19.0.2 depending on your track
# Next.js patched versions (examples; pick your line)
npm install [email protected] # or [email protected] or the latest patched in your series
Why both? The RCE lives in RSC, and the framework hardens how the protocol is handled. You want both defenses in place.
Day 2–3: Canary with blast‑radius gates
Stand up a canary environment identical to prod except for traffic share. Route 1–5% of production traffic from a non‑critical region or partner segment. Gate the rollout behind feature flags so you can revert without a redeploy. Instrument aggressively: error rates, cold starts, latency at RSC endpoints, memory pressure, and any WAF signals that correlate with large or malformed Flight payloads.
Day 3–4: Edge/WAF defenses—without going down
Yes, WAF can help catch exploit attempts, but we’ve all seen how fast, global rules can tip over fleets. If you run a managed edge, ship rules in three stages: log‑only, challenge, then block. Keep each stage in a separate config object so rollback is a one‑click revert, not a surgical change under stress.
Safe rollout pattern:
- Stage 1 (log‑only): Deploy signatures for oversized or malformed RSC payloads and suspicious content‑type overrides. Run this for at least 60 minutes under real traffic. Watch memory and CPU on the proxy tier if you change body parsing thresholds.
- Stage 2 (challenge): For traffic matching the rule from untrusted geos or ASN ranges, interpose a lightweight challenge (no captcha for legitimate bots). Monitor error budgets.
- Stage 3 (block): Turn on blocking after you confirm no false positives from Stage 2. Keep per‑zone overrides for high‑throughput APIs that might legitimately post large bodies.
If you need a refresher on avoiding edge‑induced incidents, our write‑up on how to ship WAF fixes without going down covers guardrails you can copy.
Day 4–5: Validate e2e and performance regressions
RSC patches can subtly change rendering, streaming, and caching behavior. Exercise SSR pages, error boundaries, suspense waterfalls, data loaders, and image pipelines. Compare TTFB/P95 latency versus pre‑patch baselines. If your app leaned on internal RSC behavior (we’ve seen this), you may need small refactors—do them now while canary is tiny.
Day 5–6: Roll out to 25–50% with observation SLOs
Increase traffic share, but gate on error/latency SLOs. If you cross thresholds, auto‑rollback to the previous stable.
Day 6–7: Full rollout and lock in provenance
Promote the patched build to 100%. Produce a signed SBOM with exact versions and a deployment attestation (commit SHA, build time, artifact digest). Save it to your compliance repo. If a customer asks who patched what, and when—this is your answer.
Day 7–10: Patch the follow‑ups
On December 11, two additional RSC vulnerabilities were disclosed (DoS and source exposure). They’re not RCE, but they do matter for availability and secrets hygiene. Move up to 19.0.2/19.1.3/19.2.2 and the corresponding Next.js patch in your line. Repeat a shortened canary (2–4 hours) since the blast radius is lower.
Day 10–12: Prove you’re not silently vulnerable
Add runtime detectors. Look for spikes in 4xx/5xx tied to RSC endpoints, unusually large POST bodies to RSC routes, or deserialization errors. If your logs don’t label RSC traffic, tag it at the router so you can separate signal from noise. Consider a honeypot endpoint that mimics an RSC server function but never executes; anything hitting it is a high‑confidence probe.
Day 12–14: Close the loop—communicate and memorialize
Ship a customer‑facing status note: affected/not affected, what you changed, final versions, and how to contact support. Internally, publish a one‑page after‑action with dates and owners. Update your “critical patch” runbook so the next time isn’t improvisation.
Commands and checks you can copy
Inventory:
# List vulnerable RSC packages
npm ls react-server-dom-webpack react-server-dom-parcel react-server-dom-turbopack || true
# Print all react-related versions pinned in lockfile
npm ls react react-dom | head -n 50
# Search your repo for App Router (Next.js)
rg "^app/" -n || grep -R "^app/" -n
Pin known‑good versions:
# Example: pin to the 19.2.2 line and a patched Next.js
npm install --save-exact [email protected] [email protected] [email protected]
npm install --save-exact [email protected]
Detect likely probes (customize for your stack):
# Pseudocode: flag oversized/invalid RSC Flight payloads
if request.path.startsWith("/app/") and request.method == "POST":
if content_type not in ["application/json", "multipart/form-data"]:
flag("unexpected content-type for RSC candidate")
if request.body.size_mb > 1:
flag("suspiciously large RSC payload")
People also ask
Does disabling React Server Components fix React2Shell?
Disabling RSC removes the primary attack surface, but it’s not a clean fix if your app or framework still links the vulnerable packages or exposes server function endpoints. Teams often discover transitive dependencies keep the code in the tree. Treat “disable RSC” as a last‑ditch mitigation while you roll forward to patched versions—and make sure you block any endpoints that still deserialize Flight payloads.
Are Next.js Pages Router apps safe?
Pages Router isn’t directly affected by the RSC deserialization bug. That said, many apps mix Pages and App Router, share API routes, or deploy middleware that touches RSC traffic. Don’t self‑certify by architecture alone; scan your dependencies and verify what actually runs in production.
Can a WAF reliably block this exploit?
It can raise the bar and catch unsophisticated attempts, especially oversized or malformed Flight payloads. But WAFs aren’t semantic RSC decoders, and global config flips can create outages if you change body parsing or buffering behavior at scale. Use a staged rollout (log → challenge → block), per‑zone overrides, and tight monitoring to avoid collateral damage.
Common gotchas we’ve seen this week
Build cache lies. CI pulled patched react-server-dom-* but Docker layers kept the old lockfile. Bust caches on the upgrade PR and verify the final container includes the new versions. Another one: mixed minor lines. Someone updated react but not react-dom or the RSC package, leading to subtle hydration errors. Update them together. Finally, overly aggressive WAF changes. Increasing body buffers fleet‑wide without testing can pressure memory on older proxies. Stage it, and measure.
Proof customers and auditors will accept
Security leaders don’t want a Slack message that says “we updated.” They want artifacts. Produce a signed SBOM (CycloneDX or SPDX), attach your deployment attestation (build ID, commit SHA, artifact digest, environment), and include a short test plan demonstrating that RSC endpoints reject tampered payloads. Save it in your compliance folder and reference it in your customer note.
Executive memo template (paste into email)
Subject: React2Shell (CVE‑2025‑55182/CVE‑2025‑66478) — patched
Summary: On December 3, a critical RCE was disclosed in React Server Components with downstream impact in Next.js. We upgraded to patched React (19.2.2) and Next.js (16.0.7) on December XX at HH:MM UTC. WAF rules are deployed in block mode with no observed false positives. No malicious activity detected in logs after YY hours of targeted queries. Attached: SBOM, deployment attestation, and test report.
Strategic takeaways (so you don’t repeat this fire drill)
First, reduce your RSC blast radius. If an app doesn’t need server components, don’t enable them by default. Second, treat framework upgrades like security patching, not feature work. Keep minor lines current to make emergency updates painless. Third, pre‑design your edge rollout: separate log/challenge/block configs and rehearse rollback. Finally, get in the habit of proving—not just proclaiming—remediation.
Related field guides
If you’re running Next.js App Router, bookmark our Next.js CVE‑2025‑66478 breakdown. For safe edge changes, read how to ship WAF fixes without going down. And if you need a deeper remediation cadence, our React2Shell: Patch, Prove, Prevent and 30‑day RSC hardening plan cover longer‑horizon work.
What to do next
- Today: Patch to React 19.0.2/19.1.3/19.2.2 and a patched Next.js line; run a 1–5% canary.
- Within 48 hours: Stage WAF rules (log → challenge → block), instrument RSC endpoints, and publish a brief customer notice.
- This week: Generate SBOM + attestation, add runtime detectors, and rehearse edge rollback.
- This month: Trim RSC usage, standardize framework update cadences, and codify the 14‑day playbook into your runbooks.
Want a second set of eyes on your rollout? Our team ships, patches, and scales React stacks for a living. See what we do and reach out via contacts. Move fast—safely.
