The vulnerability that wouldn't stay fixed
On December 3rd, 2025, the React team disclosed something almost every frontend engineer hoped they'd never see: a pre-authentication remote code execution vulnerability in React Server Components, rated a perfect 10.0 on the CVSS scale. Nicknamed "React2Shell" by researchers, CVE-2025-55182 meant that an unauthenticated attacker could send a single crafted HTTP request to a vulnerable server and run arbitrary code on it. Not "gain access to some data." Full compromise.
The scary part wasn't the bug itself — deserialization flaws happen. The scary part was the blast radius. React Server Components sit underneath React 19, Next.js 13 through 16, and most of the modern RSC-enabled framework ecosystem. If your app supported Server Components at all, you were potentially exposed, even if you never wrote a single Server Function yourself.
Then it happened again. And again.
Teams patched over the holidays, breathed out, and moved on. Then on December 11th, security researchers poking at the original patch found two more vulnerabilities — this time denial-of-service and source-code exposure bugs, hiding in the same code path. Teams patched again.
Then, on January 26th, 2026, a third round landed: CVE-2026-23864, another high-severity denial-of-service issue, revealing that the December 11th fix had itself been incomplete. If you'd updated to 19.0.3, 19.1.4, or 19.2.3 and stopped there, you were still vulnerable. The real fix required 19.0.4, 19.1.5, or 19.2.4.
By the time the dust settled in late January, most teams had patched React three separate times in under two months for what started as a single disclosure.
What this actually means for how you build
It's tempting to read this as "React had a bad month." The more useful takeaway is structural. Server Components collapse the line between "code that runs in the browser" and "code that runs with server privileges," and that collapse is exactly where a request-handling bug turns into full remote code execution instead of a client-side inconvenience.
A few habits came out of this saga worth keeping permanently:
Pin and monitor, don't just install and forget. Teams running Dependabot or Renovate with auto-merge on patch versions caught these fixes within hours. Teams doing manual quarterly dependency reviews were still exposed a month later.
Know your actual attack surface. "We don't use Server Functions" wasn't a safe assumption — apps that merely supported Server Components were still vulnerable through the shared deserialization path.
Read the second patch note, not just the first. The most damaging version of this story wasn't the initial CVE. It was teams who patched once in December, saw the incident "resolved," and missed the January follow-up entirely.
The upside
To React's credit, disclosure and patch turnaround were fast at every stage, and the team was transparent about the incompleteness of earlier fixes rather than quietly rolling a fix into a routine release. That's the right way to handle it. But the incident is a good reminder that "critical vulnerability, patched" is rarely a single event — it's a process, and the work usually isn't done after the first npm install.



