In December 2025, a single HTTP request — no login, no credentials, no special knowledge — could execute arbitrary code on any default Next.js 15.x or 16.x server in the world.
That's not a hypothetical. That's CVE-2025-55182, a.k.a. React2Shell. CVSS score: 10.0. Proof-of-concept exploits were public within 24 hours. Thousands of exploit attempts were observed on canary networks shortly after.
If you run Next.js in production, you need to understand what happened — and more importantly, what to do about it.
The CVEs, Quickly
CVE-2025-29927 — Middleware Authorization Bypass (CVSS 9.1)
Next.js uses an internal header, x-middleware-subrequest, to prevent routing loops. The problem: attackers could send that header themselves and trick the framework into skipping middleware entirely.
If your auth checks lived in middleware — as countless tutorials recommend — an attacker could bypass them with a single crafted request. Affects versions 11.x through 15.2.2.
CVE-2025-55182 / CVE-2025-66478 — React2Shell (RCE) (CVSS 10.0)
Insecure deserialization in the React Server Components "Flight" protocol allowed unauthenticated remote code execution. Because App Router uses RSC by default, every standard Next.js 15.x and 16.x deployment was affected out of the box. The Next.js team released an emergency patch tool (npx fix-react2shell-next) just to keep up.
CVE-2025-55183 / CVE-2025-55184 / CVE-2025-67779 — RSC Source Leak & DoS (High/Medium)
Two more issues surfaced within weeks of React2Shell: one exposed Server Function source code in certain configurations, another allowed a crafted request to hang the server process indefinitely. The initial DoS patch was incomplete and required a second fix. Classic patch archaeology.
Why This Keeps Happening
Three critical RSC vulnerabilities in a single month is a pattern, not bad luck.
Server Components run on your infrastructure. When RSC has a deserialization flaw, it's not "someone sees a wrong price" — it's arbitrary code execution on your production server. A pure client-side React app simply cannot have this class of problem. There's no server executing untrusted inputs.
Middleware is a seductive single point of failure. Security professionals have warned against single-chokepoint auth for years. CVE-2025-29927 is what that warning looks like in production. If middleware is your only auth layer, you have no auth layer.
Framework magic compounds risk. App Router, RSC, SSR, ISR, Edge Runtime, Server Actions — each feature is new surface area. Each interaction between features is a potential edge case. The more a framework does for you, the more it can do to you.
What You Should Do Right Now
1. Never rely solely on middleware for auth. Validate sessions and permissions at the API route or Server Action level, close to your data. CVE-2025-29927 would have been a non-event for apps that did this.
2. Strip internal headers at your reverse proxy.
Headers like x-middleware-subrequest should never arrive from external clients. Add them to your Nginx, Caddy, or load balancer blocklist. Takes five minutes.
3. Run npm audit in CI — as a hard gate, not a warning.
Teams that treat security failures as advisory will eventually ship a critical CVE. Fail the build.
4. Rotate your secrets if you were unpatched during React2Shell. If your app was online and unpatched in early December 2025, rotate everything — API keys, tokens, database passwords. The Next.js team explicitly recommended this.
5. Validate all inputs server-side with a schema library. Zod is the community standard. Every Server Action and API route should reject unexpected input shapes before they touch your business logic.
The Uncomfortable Question: Should You Still Be Using Next.js?
Honestly, it depends on what you're building.
| Use Case | Recommendation |
|---|---|
| Marketing site / blog | Astro or plain React + static hosting. You're carrying RSC risk with almost none of the benefit. |
| Internal dashboard | React (Vite) + separate API. SPA + API sidesteps this entire vulnerability class. |
| E-commerce / SEO-heavy app | Stay with Next.js — the SSR/ISR benefits are real. Apply the mitigations here seriously. |
| Complex SaaS product | Evaluate Remix or SvelteKit. Their server/client boundaries are more explicit and auditable. |
If you're running a CRUD app for 200 internal users with 30 Server Components because the tutorial used them, you've accidentally enrolled in an advanced security program you didn't sign up for. Plain React with a REST API is not a step backwards.
Three Layers of Defense — You Need All Three
Patching is reactive. These controls are proactive.
At the code level: Use eslint-plugin-security to catch eval(), unsafe regexes, and HTML injection at dev time. Write integration tests that explicitly verify protected routes reject unauthenticated requests — if CVE-2025-29927 existed in your codebase, a test checking that /admin returns 401 without a session would have caught it immediately.
At CI level: Combine npm audit (hard-fail on High/Critical) with an SCA tool like Snyk or Socket.dev for dependency chain analysis. Add secret scanning with truffleHog or GitHub's native scanner. If you're containerizing your app — and you should be — scan the image with Trivy or Grype before it hits your registry.
At the platform level: This is where most teams fall short. CI steps can be commented out under deadline pressure. A deployment-level policy gate can't. It blocks the rollout before it reaches users, regardless of what happened upstream.
How PipeOps Enforces This Automatically
Setting up all of the above manually is genuinely tedious — which is why most teams don't do it until after an incident.
PipeOps builds security scanning directly into the deployment pipeline, in your project settings. No separate toolchain. No third-party integration to maintain.
The Security Policy feature lets you configure:
- CVE thresholds by severity : set Critical threshold to
0and any deployment containing a Critical CVE is blocked before it ships. React2Shell (CVSS 10.0) would never have reached production. - CVSS score gate : block on raw score (0–10) rather than just categorical labels, so you catch edge cases that don't fit neatly into a severity bucket.
- Secrets detection : halt deployment if credentials are found in source code. Your last line of defense against an accidental key commit becoming a production incident.
- Granular thresholds : different rules for Critical, High, Medium, and Total count, so you can tune to your risk tolerance without blocking every deployment over a low-severity finding in an unused transitive dependency.
The key difference: this check happens at the deployment boundary, enforced at the platform layer. Cutting corners requires deliberately changing the security policy — not just commenting out a pipeline step.
The Bottom Line
The Next.js CVE trend isn't a reason to panic — the framework is too widely used and too well-resourced to be abandoned. But three RSC vulnerabilities in a single month is telling you something real: server-side rendering complexity has security costs, and those costs need to be managed actively.
The playbook is clear: patch promptly, never make middleware your only auth layer, question whether RSC complexity is justified for your use case, and enforce security scanning at all three layers — code, CI, and platform.
Security isn't a feature you ship once. It's a posture you maintain.
The good news: most of the controls described here are either free, already part of your stack, or a few settings away in your deployment platform.
Enforce security policy gates on your Next.js deployments with PipeOps →