React2Shell is the kind of bug that compresses a month of security work into a few days. Disclosed on December 3, 2025 as CVE-2025-55182, it’s a CVSS 10.0 unauthenticated RCE in React Server Components (RSC). The downstream Next.js advisory (CVE-2025-66478) followed with patched releases. Within a day, threat actors began firing probes at anything that looked like an RSC endpoint. If your React or Next.js app with App Router was online this week, treat it like an incident—patch, then prove you’re clean.
What changed this week (dates, versions, impact)
Here’s the data you can take to your CTO and risk team:
– December 3, 2025: The React team disclosed an unauthenticated RCE in RSC (“Flight” protocol) affecting react-server-dom-* packages. Affected versions: 19.0, 19.1.0, 19.1.1, 19.2.0. Fixed versions: 19.0.1, 19.1.2, 19.2.1.
– Same day: Framework maintainers began shipping patches. Next.js published its advisory (CVE-2025-66478) for App Router users with fixed versions across 15.x and 16.x release lines. Not affected: Pages Router apps, stable 14.x, and Edge Runtime.
– December 4, 2025, 1:00 PM PT: If your Next.js app was online and unpatched at this time window, rotate secrets. That’s not drama—that’s prudent hygiene when exploitation attempts are observed in the wild.
– Hosting/CDN vendors shipped temporary mitigations and WAF rules. Helpful, but not a substitute for upgrades.
Risk in plain English: the vulnerable decoding logic lets an attacker send a crafted request to a server function endpoint (or any RSC-enabled surface) and run server-side JavaScript without auth. Even if you never wrote a custom server action, you can be vulnerable if your build supports RSC.
Am I vulnerable if I don’t use Server Actions?
Possibly. If your app supports RSC (even without explicit server actions), older packages in the RSC transport layer may still deserialize attacker-controlled payloads. Audit your lockfile and your framework version; don’t rely on “we never used actions” as a defense.
React2Shell: the decisive 7‑day playbook
This is the sequence we run on production teams. Tweak for your org, but keep the order.
Day 0–1: Patch deterministically
React apps without a framework:
npm install react@latest react-dom@latest \
[email protected] \
[email protected] \
[email protected]
Next.js App Router:
# upgrade to the fixed line you’re on
npm install [email protected] # if you’re on 15.0.x
npm install [email protected] # 15.1.x
npm install [email protected] # 15.2.x
npm install [email protected] # 15.3.x
npm install [email protected] # 15.4.x
npm install [email protected] # 15.5.x
npm install [email protected] # 16.0.x
If you’re on canary for PPR, update to the patched canary (15.6.0‑canary.58 or 16.1.0‑canary.12). If you were on 14.3.0‑canary.77+ for early features, move to stable 14.x or the patched 15/16 lines.
Lock it down: delete package-lock.json/pnpm-lock.yaml diffs that reintroduce older react-server-dom-* transient versions. Run npm ls react-server-dom-webpack and confirm only 19.0.1/19.1.2/19.2.1 appear.
Day 0–2: Prove the patch is live
– Rebuild with a clean cache. For CI, force an install from scratch.
– Smoke-check SSR and server actions in staging, then production. Minimal requests should not return 5xx; malformed payloads should not trigger server execution.
– Verify runtime by logging the resolved package versions at boot. Don’t assume the Docker layer or a monorepo hoist picked up the change—show it.
Day 1–3: Rotate and restrict
– If your app was online and unpatched after December 4, 2025 at 1:00 PM PT, rotate cloud credentials, database users, OAuth secrets, and signing keys. Start with highest blast radius: production DB, object storage, and CI/CD tokens.
– Re-issue session secrets and invalidate old sessions. If you terminate sessions on deploy, communicate to customer support before users get surprised.
– Reduce IAM where you can. If your app server can write to buckets, move it to read-only plus a narrow write path.
Day 2–4: Hunt for compromise
Look for four classes of signals:
– Suspicious HTTP fingerprints: requests with headers like next-action or rsc-action-id, unexpected multipart/form-data or application/x-www-form-urlencoded bodies hitting RSC endpoints, and payloads containing strings such as constructor, __proto__, prototype, or _response.
– Process anomalies: Node.js spawning child_process, outbound connections to IPs you don’t expect, or shell utilities like curl/wget appearing in containers that never use them.
– File system drift: newly created files in /tmp, app .next/server output, or uploaded artifacts within the last 72 hours.
– Credential access: error logs mentioning failed metadata calls, STS tokens, or cloud provider IMDS probes.
Quick queries to start (adapt for your log stack):
// search reverse proxy / CDN logs
where http.request.headers["next-action"] exists
or http.request.headers["rsc-action-id"] exists
or (http.request.headers["content-type"] contains "multipart/form-data"
or http.request.headers["content-type"] contains "application/x-www-form-urlencoded")
and http.request.body contains any ("constructor","__proto__","prototype","_response")
# in Linux hosts/containers, list recent executables and outbound sockets
find / -xdev -type f -executable -mtime -3 2>/dev/null
ss -tp | grep node
Day 4–7: Harden permanently
– Web Application Firewall: add a targeted rule to block RSC exploit patterns (look for next-action/rsc-action-id request headers plus those telltale payload keys). Validate in staging, then enforce. Managed rule sets can help, but keep your custom rule until you’re confident your fleet is uniformly patched.
– Rate limit and shield: enforce per‑IP limits on POSTs to your RSC endpoints and require auth where it doesn’t break UX.
– Observability: add a dashboard that breaks out traffic with RSC headers and body content type. Alert if sudden spikes occur.
– Build hygiene: pin safe versions and add an allowlist for react-server-dom-* package ranges in Renovate or Dependabot.
How to verify your fixes (don’t guess—show receipts)
Here’s a five‑step verification flow we ask every team to document:
1) Evidence of correct dependency versions: attach the exact npm ls output for react, react-dom, and each react-server-dom-* package. For Next.js, copy the next version from package.json and node_modules/next/package.json in the image layer that actually shipped.
2) Deployment artifact hash: record image digests or provenance signatures. If you use supply chain signing, verify the attestations for the release that picked up the patch.
3) Runtime boot log: add a startup log line printing the loaded versions. This prevents “built the fix, but rolled back at runtime” surprises.
4) Negative test: replay a known malformed RSC request against staging. Expect a controlled 4xx/5xx without code execution side effects. Keep the pcap/log for audit.
5) Monitoring and alerting: screenshot of your alert in place for RSC headers and body patterns. Set a 90‑day retention on those logs.
People also ask: do WAF rules actually help against React2Shell?
They help you buy time and detect noise, not replace patches. A solid rule is to treat WAF as a guardrail: block obvious exploit payloads and log the rest. Keep the rule active until you’ve confirmed every service is on safe versions and your attack surface is reduced.
People also ask: which Next.js versions are fixed?
Fixed releases across 15.x and 16.x include 15.0.5, 15.1.9, 15.2.6, 15.3.6, 15.4.8, 15.5.7 and 16.0.7. Canary users should be on 15.6.0‑canary.58 or 16.1.0‑canary.12. If you’re stuck on 14.3.0‑canary.77 or later canary builds, move to stable 14.x or to a patched 15/16 line.
A practical WAF rule outline you can adapt
Below is a conceptual skeleton you can translate to your provider’s config. Don’t paste it blindly—test and tune for false positives:
IF request.headers contains any of ["next-action", "rsc-action-id"]
AND request.headers["content-type"] contains any of ["multipart/form-data", "application/x-www-form-urlencoded"]
AND request.body contains any of ["constructor", "__proto__", "prototype", "_response"]
THEN block and log at high severity
Pair that with a rate limit on suspicious POSTs to RSC endpoints, and you’ll cut noise dramatically while you patch.
Edge cases and gotchas we’ve seen this week
– Monorepos with mixed frameworks: One package updated, another still pulls a vulnerable RSC package via a transitive dependency. Solution: run npm ls react-server-dom-webpack from each app root and inside production images.
– Docker layer caching: The Dockerfile installs dependencies before copying package.json, so the patched versions never build in CI. Solution: move package.json/lockfile earlier in the Dockerfile and force cache busting when versions change.
– Auto‑rollback: Health checks fail for unrelated reasons; the platform rolls back to a vulnerable image. Solution: pin health checks to healing thresholds and temporarily require manual approval to roll back during the patch window.
– Non‑Next RSC adopters: React Router RSC preview, Vite RSC plugin, Parcel RSC, Waku, and other early adopters also needed updates. Track each independently; don’t assume your framework carries every fix.
React2Shell checklist for CTOs and engineering managers
- Is every production and pre‑prod environment on fixed RSC/Next.js versions? Show artifact hashes.
- Have we rotated secrets if we were unpatched and online after December 4, 2025 1:00 PM PT?
- Do we have a WAF rule on the edge for RSC patterns, with alerting?
- Can we produce logs proving no suspicious RSC requests were processed successfully?
- Did we run a targeted threat hunt for child processes, outbound beacons, and filesystem drift?
- Is Renovate/Dependabot configured to pin safe ranges for
react-server-dom-*andnext?
Cost of waiting: a realistic scenario
Picture a retail site on Next.js 15.2.x with App Router. Traffic is peaking for holiday promos. You delay upgrades because “the canary looks fine.” A botnet sprays malformed RSC requests for hours. One edge node routes a vulnerable image that wasn’t rebuilt; a server action deserializes junk; an attacker drops a crypto‑miner and scrapes temporary credentials. Your cloud bill spikes, sessions reset, and you spend a week writing incident reports. This isn’t fear—this is how low‑skill RCE campaigns pay off at scale.
What success looks like 7 days from now
You’ve upgraded all apps; you can prove it with SBOMs and version logs. Your WAF is cutting noise and alerting properly. You rotated secrets and tightened IAM. You’ve documented a negative test and added a playbook entry in the on‑call runbook. You’re ready for the next advisory—not scrambling to remember what “Flight” means.
What to do next
- Run the upgrades now and verify with a clean CI build. Capture
npm lsoutput for audit. - Rotate high‑risk secrets if you were online and unpatched after December 4, 2025 1:00 PM PT.
- Deploy an RSC‑focused WAF rule and add log‑based alerts for
next-action/rsc-action-id. - Threat hunt for process/file anomalies and outbound connections from Node.js.
- Set up dependency policies to pin safe RSC ranges going forward.
Want hands‑on help?
If you need a second set of eyes or help hardening your CI/CD, we’ve already published deep dives on this family of issues. See our 72‑hour React2Shell patch plan, our Next.js CVE‑2025‑66478 patch and verification guide, and our pragmatic React2Shell playbook. If this triggered broader platform work (runtime upgrades, runtime flags, or TLS secrets rotation), our Node.js December 2025 patch runbook can help you schedule zero‑drama changes.
Need an experienced crew to perform the hunt and hardening with you? Start a conversation on our services page and we’ll map a 7‑day plan tailored to your stack.
FAQ: fast answers for stakeholders
Is Pages Router affected?
No—Next.js Pages Router isn’t impacted by this specific issue. The risk centers on App Router with RSC. Still, check your lockfile for stray react-server-dom-* versions and keep to patched React.
Do we need to take downtime?
Most teams can perform rolling deploys. If your edge caches or SSR nodes differ by region, verify each region’s image digest; don’t assume global propagation.
Can we rely on our CDN’s emergency mitigation?
Treat CDN mitigations as a seatbelt, not a force field. They reduce risk and buy time. They don’t patch your code, and attackers iterate fast.
What evidence do auditors want?
Version inventories, deployment artifact hashes, a negative test proving no code execution from a malicious RSC request, and a threat hunt report summarizing findings—especially around credentials and outbound traffic.
Zooming out: this isn’t the last critical deserialization bug we’ll see in JavaScript land. But if you execute the 7‑day plan above, you’ll convert a chaotic week into a tidy audit trail—and sleep better knowing your RSC surfaces are patched, monitored, and ring‑fenced.