Next.js October 2026 Security Update: Patching Two Critical RCEs
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
| Advisory | What it is | Severity |
|---|---|---|
GHSA-673q-mjm6-r5xr | RCE in the App Router with Cache Components, when a use cache function returns typed arrays | Critical |
CVE-2026-96889 | RCE in the Image Optimization API when it processes SVG files — a memory-safety bug in librsvg, reached through sharp | Critical |
GHSA-p3m5-59mp-jv5r | Denial of service in App Router Server Actions | High |
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:
- It uses
next/imagewith 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. - 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 withunoptimizedinstead, which skips the optimizer entirely. - Keep
images.remotePatternsnarrow. 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,reactandreact-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
- Next.js blog — official security posts and the July 2026 announcement of monthly security releases
- Brandefense: Next.js security update, October 2026
- HOL: CVE-2026-96889 write-up
- Zero Day Observer: upgrade to 16.4.1 or 15.5.28
- endoflife.date: Next.js support lines