Critical Vulnerability in React and Next.js
Why Next.js users got hit hardest, and the exact steps you need to take to protect yourself
[
I was having one of those rare quiet mornings where everything just… works.
Code compiles. Tests pass. Coffee’s still warm.
And then a friend messages me: “Dude, React can run arbitrary commands on the server. Like… system level commands.”
I laughed.
The kind of laugh you do when you think somebody’s joking but also pray they’re joking because you already know they’re not.
Five minutes later, I’m staring at a terminal where a Next.js app — a fresh install, mind you — is happily executing
id reboot
And then the VM powers off.
That is the moment my coffee went cold.
Let’s break down exactly what happened, why this vulnerability is as bad as it gets, and what you need to do right now so you (and your job, your production app, and your sanity) don’t go down with it.
What Actually Happened? (No Sugarcoating)
A critical vulnerability — CVE-2025–55182 — hit React Server Components (RSC), enabling attackers to execute arbitrary system commands on the server.
Not JavaScript injection. Not XSS. Not some quirky dev-mode-only bug.
Actual system level commands.
That means
- Creating files
- Deleting files
- Reading secrets
- Running reverse shells
- Shutting down your servers
The works.
The vulnerability has been affectionately (or traumatically) nicknamed React to Shell, a nod to the infamous Log4Shell nightmare from 2021.
This is the kind of bug that keeps security teams awake and DevOps teams updating their LinkedIn profiles.
Why Next.js Users Got Hit the Hardest
React on its own?
You have to opt in to server components.
Next.js?
You’re opted in by default.
Congratulations. You played yourself.
If you installed a vanilla Next.js 14+ app using the app/ directory structure, you were running React Server Components on day one — whether you realized it or not.
And because RSC sits between your app and the database or backend logic, compromising RSC means compromising the whole server.
This is why the demo showing a plain Next install rebooting a VM was possible. No custom code. No weird configuration. Just defaults.
Let that sink in.
Image edit:- Mark
How the Vulnerability Actually Works (In Human Terms)
I’m not going to drown you in protocol diagrams or thousand line diffs.
Here’s the honest, high level explanation
React Server Components uses a protocol called Flight, which serializes data and ships it across the wire.
Objects get serialized. Objects later get de‑serialized.
Nothing unusual so far.
The Fatal Mistake
During deserialization, React didn’t properly verify that certain fields in the serialized data actually belonged there.
If an attacker crafted a malicious payload using Flight’s own object‑reference syntax, they could
- Reach into prototype chains they shouldn’t access
- Grab the Function constructor
- Invoke it with arbitrary JavaScript
- Use Node.js APIs (like
child_process) - Run system commands
It’s the JavaScript equivalent of handing someone your house keys because they told you they “felt like they belonged on the keychain.”
The vulnerability is elegant, terrifying, and a reminder that serialization is the devil.
Image edit:- Mark
Reality — This Bug Was Practically Designed for Attackers
Let’s be blunt.
When your server automatically
- Parses user controlled input
- Deserializes objects
- Pulls in constructors dynamically
- Runs JavaScript on the backend
…you’re begging for a security event.
This bug isn’t surprising. The only surprising thing is that it didn’t happen sooner.
JavaScript lets functions be treated as data. Serialization lets data become code. Backend rendering runs that code with server permissions.
That trifecta is powerful. It’s also a minefield.
What You Need to Do Right Now
Let’s skip the fluff and get straight to the checklist.
1. Upgrade React Immediately
React released patched versions
- React 19.0.1
- React 19.1.2
- React 19.2.1
If you’re on React 18 and using RSC indirectly through a framework, your framework’s patch matters more.
2. Upgrade Next.js
Next.js teams have released patched versions for active minors.
If you’re on Next 14.3.x:
Downgrade to 14.0.0 OR upgrade to the latest patch — the broken code was isolated to 14.3.
3. Redeploy Fresh Servers
I’m not kidding.
If your machine was exposed publicly and you weren’t sandboxing, assume compromise. Tear down the server. Re-deploy clean infrastructure.
Containers? Rebuild.
EC2? Replace.
Bare metal? You have my condolences.
4. Rotate Secrets
If the server could execute shell commands, assume
- env vars were read
- files were accessed
- tokens were exfiltrated
Rotate everything.
Yes, even the annoying ones.
5. Audit Logs for Strange Behavior
Look for
- Unexpected outbound connections
- Suspicious processes
- Restart events
- Weird artifacts in
/tmp
If you see something bizarre, don’t rationalize it. Servers don’t reboot themselves because “maybe the kernel hiccuped.”
The Uncomfortable Lesson
Every few years the universe reminds us that abstraction doesn’t eliminate complexity — it just moves it somewhere else.
We wanted
- Cleaner components
- Better DX
- Snappy server-rendered UIs
Instead we got
- Arbitrary code execution
- Devs yelling on Twitter
- A mass migration to the React issue tracker
Innovation is cool. Security still matters.
And when frameworks try to collapse too many layers together, the blast radius of a single bug becomes catastrophic.
So… Would Rust Have Saved Us?
Short answer?
Probably not.
Serialization is risky in any language when you mix code and data.
Rust serializers (like Serde) avoid shipping code across the wire entirely — which is good.
But RSC’s design is fundamentally more complex because it’s not just shipping JSON — it’s shipping component instructions and behavior.
Language choice alone doesn’t solve architectural risks.
Finally — And a Call to Action
If your stack uses React Server Components, this is your wake‑up call.
Security isn’t a feature you sprinkle on later. It’s a design constraint.
And ignoring it is how we end up with CVEs that can reboot your VM from a single HTTP request.
But hey — at least we learned something, right?
If this article made you rethink your setup, share it with a teammate.
Tell me what you think React should’ve done differently.
Save this so you can refer back when you’re patching your app.
Just don’t ignore it.
Because “modern web development” is already chaotic enough without attackers joining the party.
Stay safe out there.

