React Security: Patch, Check and Harden Your Next.js App

Table of Contents
You ship a Next.js app on the App Router. Someone in the team chat posts a link about a React Server Components vulnerability with a CVSS score of 10.0, and the next message is “are we affected?” Nobody answers for a while, because nobody is sure which package versions the app actually runs.
This is how I would answer that question, then how I would check the everyday React and Node.js risks while the repo is open anyway.
What was the React Server Components vulnerability?
On 3 Dec 2025, React disclosed CVE-2025-55182, and React rates it CVSS 10.0. It sits in the server packages that run Server Components: react-server-dom-webpack, react-server-dom-parcel and react-server-dom-turbopack. The affected versions are 19.0, 19.1.0, 19.1.1 and 19.2.0.
On 11 Dec 2025, React disclosed more flaws in the same area. CVE-2025-55184 and CVE-2025-67779 are denial of service flaws, rated 7.5, and CVE-2025-55183 exposes source code, rated 5.3. Some early fixes were incomplete, so React says to use 19.0.4, 19.1.5, 19.2.4 or later. On 26 Jan 2026, React updated the post again with CVE-2026-23864, rated 7.5.
The latest React release is 19.3, from 9 Sep 2026. So the advisory history is long, and the safe reading is that “we patched in December” does not settle anything.
The first thing I would run is a list of what is installed, from the lockfile, without guessing:
npm ls react react-dom next
npm ls react-server-dom-webpack react-server-dom-parcel react-server-dom-turbopack
Does it affect my Next.js app?
Next.js tracked this as CVE-2025-66478. Next.js 14.x stable, the Pages Router and the Edge Runtime were not affected. That first fix is now old, though. On 14 Oct 2026, Next.js shipped more security fixes on its LTS lines, so the answer is to use the latest patch for your line, and not to stop at the December 2025 fix.
| Your setup | What I would do |
|---|---|
| App Router on Next.js 15 or 16 | Update to the latest patch on your line |
| Next.js 14.x stable or Pages Router only | Not affected by CVE-2025-66478; still take the latest patch |
| Edge Runtime only | Not affected by CVE-2025-66478; still take the latest patch |
To see how far behind the app is, I would start with this:
npm outdated next react react-dom
Then I would pin the newest patch on the same major line, run the build and the tests, and only then think about a major upgrade. For what changed in recent releases, see Next.js 16.4 (Indonesian).
Where does raw HTML get into the page?
The React docs warn that dangerouslySetInnerHTML can introduce an XSS vulnerability. At least the name is honest about it. I would search for every use and trace where the HTML comes from:
grep -rn "dangerouslySetInnerHTML" app components src
Each hit should get HTML you trust or have sanitized. If the answer to “where does this come from” is “a form field”, that is the bug.
Are secrets leaking into the browser bundle?
Next.js puts only NEXT_PUBLIC_ variables into the browser bundle, and other variables stay on the server. So a NEXT_PUBLIC_ name means the value is public, whatever the variable is called. I would list them and read each one:
grep -rn "NEXT_PUBLIC_" .env* app src
An API secret with that prefix is a public API secret. Move it to a server-side variable, and rotate it, because it already shipped.
Is auth checked on the server?
A check in a component hides a button. It does not protect the data behind it. Every route handler and Server Action that reads or writes data needs its own session check on the server, for example:
"use server";
export async function deleteInvoice(id: string) {
const session = await getSession();
if (!session) throw new Error("Unauthorized");
// delete only after the check
}
getSession here stands for whatever auth helper the app already uses. For route patterns, see Next.js App Router API.
What about the Node.js side?
npm audit sends a description of your dependencies to the registry and reports known vulnerabilities. It exits with a non-zero code when it finds any, so it can fail a CI job. By default it needs a package-lock or shrinkwrap file. npm writes package-lock.json when it changes your dependency tree, so commit that file and let CI read it.
npm ci
npm audit --omit=dev
Keep secrets in server-side variables and out of the logs. Validate every request body on the server, and add rate limits to login, signup and any costly endpoint. The OWASP input validation cheat sheet covers the checks.
Which Node.js line should I run?
On 27 Oct 2026, Node.js 22 and 24 are in maintenance, and Node.js 26 starts Active LTS on 28 Oct 2026. Node.js 20 reached end of life on 30 Apr 2026, so an app still on 20 is running without security fixes.
| Line | Status | End of life |
|---|---|---|
| 20 | ended | 30 Apr 2026 |
| 22 | maintenance | 30 Apr 2027 |
| 24 | maintenance since 20 Oct 2026 | 30 Apr 2028 |
| 26 | Active LTS from 28 Oct 2026 | 30 Apr 2029 |
node -v
What about AI-written code?
On my own side projects, I let AI agents write code. On company work, I do not trust AI code until I read it and test it. I also keep dependencies few. If I can write a small part myself, I do not install a package for it.
AI tools write code fast, and they can copy an unsafe pattern just as fast. I would review that code like any other pull request, with the same searches as above. The PR review checklist for AI-generated code is the list I would use. For the long-term cost, read technical debt in AI-built apps (Indonesian).
Verdict
If the app runs the App Router, update React and Next.js to the latest patch on your line today, and treat the December 2025 versions as a floor you have already passed. Then spend the same afternoon on raw HTML, NEXT_PUBLIC_ variables, server-side auth checks, npm audit in CI and the Node.js line. If the update breaks the build and you want help getting it green, this is how I handle code fixing.
Need this built instead of read about?
Send me your project. I reply within 24 hours and tell you plainly whether I’m the right fit.
Send me your project

