Let's talk
WritingNext.js · Security · React · Upgrades

Next.js October 2026 Security Update: Patching Two Critical RCEs

By Srikanth V5 min read

On October 14, 2026, the Next.js team published an out-of-band security update: two critical, unauthenticated remote code execution vulnerabilities and one high-severity denial-of-service bug. My portfolio — the site you're reading — was on next@16.2.10 that morning. This post covers what the advisories say, how I checked whether I was exposed, and the upgrade I actually shipped.

Always read the official Next.js advisory and the GitHub Security Advisories for exact version ranges. I've linked my sources at the end; this post is my notes from patching a real production site.

What was fixed

AdvisoryWhat it isSeverity
GHSA-673q-mjm6-r5xrRCE in the App Router with Cache Components, when a use cache function returns typed arraysCritical
CVE-2026-96889RCE in the Image Optimization API when it processes SVG files — a memory-safety bug in librsvg, reached through sharpCritical
GHSA-p3m5-59mp-jv5rDenial of service in App Router Server ActionsHigh

The patched releases are 16.4.1 (Active LTS) and 15.5.28 (Maintenance LTS). 16.4.2 followed a day later with Turbopack fixes and includes the same security patches.

Why a "static" portfolio was still exposed

It's tempting to think a mostly static site has nothing to worry about. Two things made mine a real target:

  1. It uses next/image with remote images. Project logos live in Supabase Storage and go through /_next/image. The optimizer is a server endpoint that decodes images on your infrastructure — exactly the code path the image RCE lives in.
  2. The admin uses Server Actions. Every project and blog edit goes through a server action, which is the surface of the DoS bug.

And the bigger lesson: I was on a release line that no longer gets patches. The last 16.2.x release is 16.2.12, from July. The October fixes only shipped for 16.4 and 15.5. Staying on 16.2 — even its latest patch — meant staying vulnerable.

How I checked

Two commands tell you nearly everything:

npm ls next      # which Next.js version is actually installed
npm ls sharp     # which image decoder the optimizer will load

The sharp check matters. Next.js pulls sharp in as an optional dependency, and a lockfile can keep resolving an older version even after you bump next. After upgrading, make sure npm ls sharp shows the version the new Next.js asks for — on 16.4.2 that's sharp@0.35.5.

The upgrade

npm install next@16.4.2 react@19.2.9 react-dom@19.2.9 --save-exact
npm ls next sharp
npm run build

React published 19.2.9 on the same day, so I took that patch too and stayed on the 19.2 line to keep the change small. --save-exact pins the versions so a fresh install on CI can't quietly resolve something else.

Going from 16.2 to 16.4 is a minor-version jump, so I treated it like a real upgrade, not a patch:

  • Build locally and read the output for new warnings.
  • Click through every route type: static pages, dynamic [slug] pages, generated OG images, route handlers (/llms.txt, /sitemap.xml), and the admin forms that use Server Actions.
  • Check the image pipeline specifically: a remote PNG through /_next/image, and an SVG logo.

My build passed with no code changes.

What npm audit still shows (and why I left it)

After the upgrade, npm audit still reported a couple of issues in braces and postcss-selector-parser. Both come from Tailwind CSS v3's build-time tooling: the file watcher and the CSS parser. They only process files from my own repository during next build, never anything a visitor sends, so they aren't reachable from the live site. Fixing them means migrating to Tailwind v4, which is a project of its own — so it's on my list, not in this patch.

Reading audit output this way — is this code reachable by an attacker at runtime? — is the difference between a useful security review and a panic upgrade.

Hardening I kept (or added) while I was there

  • Don't turn on images.dangerouslyAllowSVG. By default the optimizer refuses to rasterise SVGs. My SVG logos are served with unoptimized instead, which skips the optimizer entirely.
  • Keep images.remotePatterns narrow. Mine allows a single Supabase hostname, not **. An optimizer that will fetch and decode any URL on the internet is a much bigger attack surface.
  • Ship security headers. I added a Content Security Policy and the rest of the standard set the same week — I wrote that up in Security headers for a Next.js site on Vercel.

Make the next one boring

Next.js now publishes security releases on a monthly schedule with advance notice, plus out-of-band releases for critical bugs like these. A few habits make that schedule painless:

  • Stay on the Active LTS line. Falling two minors behind is how a patch turns into a migration.
  • Turn on Dependabot or Renovate security updates for next, react and react-dom.
  • Subscribe to the GitHub Security Advisories for vercel/next.js.
  • Keep a short post-upgrade checklist (the bullet list above) so every upgrade gets the same checks.

If your site is on anything older than 16.4.1 or 15.5.28, upgrade today — and run npm ls sharp afterwards.

Sources

More writing