Security Guides

Running Next.js safely: not falling behind on published CVEs

The biggest Next.js risk is an unpatched published CVE. Four practices: check the running version, monitor dependencies, update fast, use least privilege.

Published 2026-06-07 Updated 2026-10-06 11 min read
On this page

For: anyone shipping apps with Next.js (or similar JS frameworks), especially "built it with AI's help, operating by feel." Distilled from a real incident (→ the neglected CVSS 10.0).

This site's view: what matters is not speed but a system that doesn't miss

When indie developers fall short at security, it is usually not from lack of knowledge but because they can't keep operations going. Reading CVE news faster than anyone has no value (leave speed to vendors and news). What works is a system that won't miss the CVEs relevant to you. So this article focuses on building that system rather than on knowing more.

1. Judge by the running version

Measure "am I on a dangerous version" by what's actually running, not the manifest floor — because the manifest number and the running version often disagree.

✗ Count by the package.json floor

"next": "^16.0.0" → "16.0.0 is vulnerable, so we are" — over-counted as "8 vulnerable".

✓ Count by the running version

npm ls next shows the resolved version → auto-bumped ones are safe, only pinned ones lag. Really 2.

The package.json floor can differ from what is actually running. Judge by the running version and the risk changes (8 'vulnerable' became 2).
# see the versions actually resolved
npm ls next react react-dom
# inside a running container
docker exec <container> npm ls next

Caret ranges (^16.0.0) auto-bump on rebuild; pinned deps lag. Judge by the versions shown here.

How to check your own setup

These steps tell you which version your app is actually running and whether a known CVE applies. Each one only inspects your own environment.

1

Check the local version

Run npx next info in the project folder. It shows the actual versions of next, react and react-dom, and how far you are behind the latest release. npx next -v prints just the Next.js version.

2

See why you have that version

npm ls next (or pnpm why next) shows which version is installed and through which package. If your lockfile (package-lock.json or pnpm-lock.yaml) is not committed, the version can change on every build, so commit it first.

3

Check the version running in production

Updating locally does not change a server still running an old image. For a container, read the version field of next's package.json inside the running container (command below). This also works with output: 'standalone'.

4

Match against known CVEs

npm audit --omit=dev checks only the dependencies that ship to production. Adding --audit-level=high makes it exit non-zero when anything High or above is found, so CI can stop on it. Scanning the lockfile with osv-scanner serves the same purpose.

5

Read the official advisory for your setup

Next.js advisories sometimes split by App Router vs Pages Router, or by self-hosted vs managed. Compare the fixed versions listed in the advisory with the versions you found in steps 1 to 3.

# local: actual versions and distance from latest
npx next info
# the version running inside the production container
docker exec <container> node -p "require('next/package.json').version"
# check only production dependencies; fail on High or above
npm audit --omit=dev --audit-level=high

What changes with how you run it

The same CVE can affect you or not depending on how you run Next.js. Two past cases, by deployment type:

How you run itMiddleware auth bypass (CVE-2025-29927)RSC RCE (CVE-2025-55182)Who updates
Managed (Vercel, Netlify, etc.)Not affected (routing runs in a separate system)Affected if you use App Router; blocking rules exist but you still must updateYou (your lockfile decides the next version)
Self-hosted (next start / standalone, incl. Docker)AffectedAffected if you use App RouterYou (through rebuilding the image and restarting)
Static export (output: 'export')Not affected (no server runs)No server receives requests, so it generally does not reach youYou (build-time dependencies still need updates)

So even on managed hosting, raising the Next.js version is your job. Treat the host's protections as buying time until you are on the patched version.

Check the support window too. Per the official support policy, as of October 2026:

LineStatus (October 2026)Security fixes
16.xActive LTS (features, fixes, security patches)Yes
15.xMaintenance LTS (two years from initial release)Critical ones only
14.x and olderUnsupportedRarely, for severe issues, with no guarantee

2. Machine-monitor your dependencies

Tracking CVEs by hand doesn't hold up, and the miss becomes the incident. Monitor them automatically with a tool.

Free dependency monitoring

osv-scanner scan -L pnpm-lock.yaml

On GitHub, enable Dependabot (the repository's Settings → Advanced Security → Dependabot alerts). You'll get PRs only for CVEs that match your deps.

What matters is prioritization. This site's stance: rank by "is it being exploited (KEV)" times "how high is the CVSS." A high CVSS you don't use is small impact; a mid-score under active exploitation is top priority. That prioritization is the core of the work.

3. Updating: move to the fixed version, not a workaround

When a vulnerability appears, upgrade the framework to the patched version to fix the vulnerability itself.

Surface-level fixes (insufficient)

  • Block only requests that look like the attack at a reverse proxy
  • Stop the charges/symptom and call it "handled"
  • Leave the RCE vulnerability itself in place

Root fix (correct)

  • Upgrade the framework to the patched version
  • After upgrading, confirm the signature is gone in your logs
  • Treat stopping the damage and fixing the root cause as two separate jobs, and do both

The common failure

"Stopped the charges/symptom" ≠ "handled." Stopping the damage and fixing the vulnerability are different jobs. Do both.

A real example: the December 2025 React Server Components vulnerability

Here is what handling a published CVE actually looked like, using the React Server Components (RSC) vulnerability disclosed in December 2025. Everything below comes from the official React and Next.js announcements and CISA's public data.

  1. December 3, 2025

    React disclosed CVE-2025-55182 (CVSS 10.0), which can lead to code execution on the server without authentication. In Next.js, App Router apps on 15.x, 16.x and some canaries were affected (CVE-2025-66478); Pages Router and the Edge Runtime were not. There was no workaround: upgrading to a fixed version (15.0.5, 15.1.9, 15.2.6, 15.3.6, 15.4.8, 15.5.7, 16.0.7 and others) was required.
  2. December 5, 2025

    CISA added it to its catalog of vulnerabilities confirmed as exploited in the wild (KEV).
  3. December 6, 2025

    Next.js added that apps online and unpatched as of December 4, 1:00 PM Pacific should rotate the secrets they use (API keys and so on).
  4. December 11, 2025

    While the patch was being examined, two more issues in the same mechanism (denial of service and source code exposure) were found and patched. The denial-of-service fix then proved incomplete, CVE-2025-67779 was issued, and people who had already upgraded were asked to upgrade again.

Three operational lessons follow:

  • One update is not the end. Follow-up fixes to the same code can arrive days apart
  • The host's blocking rules were a supplement; upgrading was described as the only complete fix
  • If you were online before patching, rotate secrets as well as updating

This site's view: done means the production version is patched, not that you ran an update

When follow-up fixes keep coming, as here, "I upgraded last week" stops being reliable. Judge completion by whether the version running in production is at or above the fixed version in the latest advisory, not by memory of the work. This site, too, only marks an update done after confirming the container was recreated and checking the version running inside it.

Common mistakes and fixes

  • Judging by the number in package.json: the installed version may differ. Check with npx next info or npm ls next.
  • Stopping after updating the lockfile: the old version keeps running until the production image is rebuilt and restarted. Check the version inside production.
  • Feeling safe after one update: follow-up advisories can come. Keep Dependabot or similar alerts on and watch advisories for a few days.
  • Leaving it to the host's blocking rules: they may not catch every form of an attack. Upgrade.
  • Staying on an unsupported line: 14.x and older have no guarantee of fixes. Plan the move to 16.x.
  • Missing production-relevant warnings among dev-only noise: run npm audit --omit=dev to see what ships first.
  • Ignoring the window before you patched: secrets may have been taken in that time. Rotate API keys and database passwords (→ .env and API key basics).

4. Least privilege to limit the damage

Design so that damage stays limited if the app is exploited.

1

Run as a non-privileged user

Don't run the container USER as root. A breach then reaches only what that user is allowed to do.
2

Bind DB/Redis to the internal network only

Never public. Reduce the directly reachable surface.
3

Separate per service

Split networks and data per service so one breach can't spread to everything.

These decide whether a breach stops at "env theft inside a container" or reaches "host takeover."

We do this ourselves

This site monitors its own dependencies for CVEs, exactly as written here — so that the kind of miss that started it all (a neglected public CVSS 10.0) isn't left to human attention again. We say "rank by priority (KEV + CVSS)" because that's how we actually operate.

Sources

FAQ

QWhat matters most for Next.js security?
A

Before not writing bugs, it's not leaving published CVEs in the framework or its dependencies unpatched. Most severe breaches come from neglected known vulnerabilities, not novel attacks.

QCan I tell if I'm vulnerable from package.json?
A

No. The `^` (floor) in package.json doesn't reflect reality — caret ranges auto-bump on rebuild, pinned deps lag. Always judge by the version actually running.

QWhat's the one thing to do first, solo?
A

Enable Dependabot (GitHub) or osv-scanner to monitor your dependencies for CVEs automatically. Manual checking always misses something. A system that keeps running is worth more than extra knowledge.

QHow do I check which Next.js version I am running?
A

Run `npx next info` in the project folder; it prints the actual versions of next, react and react-dom. For production, read the version from next's package.json inside the running container or server (step 3 in the article). Your local copy and production are not always the same, so check both.

QIf I host on Vercel or a similar platform, do I still need to update?
A

Yes. The March 2025 middleware authorization bypass (CVE-2025-29927) did not affect Vercel or Netlify, but the December 2025 React Server Components RCE (CVE-2025-55182) affected App Router apps in general. Vercel added its own blocking rules (WAF) and still said they cannot stop every variant, and that upgrading to a patched version is required.

QIs it fine to stay on Next.js 14 or older?
A

Not recommended. Under the official support policy, 14.x and older are unsupported; security fixes come only rarely for severe issues and are not guaranteed. As of October 2026 the supported lines are 16.x (Active LTS) and 15.x (Maintenance LTS). Maintenance lasts two years from the initial release, so if you are on 15.x, plan the move to 16.x as well.