Next.js & React

Next.js Security Update October 2026: Patch the use cache RCE, SVG sharp RCE and Server Actions DoS

The October 14, 2026 Next.js security update fixes two critical RCEs (use cache and SVG via sharp) and a Server Actions DoS. Check if you are affected, run a free checker script, and patch Next.js 15 and 16 on Docker or Coolify.

Next.js security update October 2026 cover: terminal showing next 16.4.0 with sharp 0.35.4 upgraded to next 16.4.2 with sharp 0.35.5
On this page
  1. What did the October 2026 Next.js security update fix?
  2. Quick definitions
  3. TL;DR: how to patch Next.js now
  4. Is my Next.js app affected?
  5. Why does npm audit say my app is safe?
  6. A script that checks your app against all three advisories
  7. How do you upgrade Next.js 16 to the patched version?
  8. How do you patch Next.js 15 safely?
  9. How do you patch a self-hosted Next.js app in Docker or Coolify?
  10. What if you cannot upgrade Next.js today?
  11. How do you know whether you were attacked?
  12. Security habits that make the next patch faster
  13. Common mistakes when patching
  14. Key takeaways

The Next.js security update of October 14, 2026 fixes three vulnerabilities: two critical unauthenticated remote code execution (RCE) bugs, one in use cache and one in SVG image optimization through sharp, and a high severity denial of service in Server Actions. Upgrade to Next.js 16.4.1 or later on 16.x, or 15.5.28 on 15.x, make sure sharp is 0.35.5 or later, then rebuild and redeploy.

The patch is easy to apply and easy to get wrong when you self-host. I reproduced the upgrade on real installs and found that upgrading Next.js 15 to 15.5.28 left the vulnerable sharp 0.34.5 in place, while npm audit on an unpatched next@16.4.0 reported 0 vulnerabilities. This guide shows how to check whether you are affected, a script that checks for you, and the exact steps to patch a Docker or Coolify deployment. Everything is cited to the official advisories.

What did the October 2026 Next.js security update fix?#

It fixed three advisories published on October 14, 2026, all patched in Next.js 16.4.1 (Active LTS) and 15.5.28 (Maintenance LTS), according to the official Next.js security update. Two allow unauthenticated remote code execution with a CVSS 4.0 score of 9.5; the third lets crafted requests pin a server's CPU.

AdvisorySeverityWhat it isAffected next versionsFixed inWorkaround
GHSA-673q-mjm6-r5xrCritical, 9.5RCE in use cache functions that return multiple typed arrays16.0.0 to 16.4.016.4.1None
CVE-2026-96889 / GHSA-2464-fhr4-w9xwCritical, 9.5RCE in the Image Optimization API with SVG, via sharp's librsvg, on glibc Linux10.0.0 to 15.5.27, 16.0.0 to 16.4.015.5.28, 16.4.1sharp 0.35.5 or later
GHSA-p3m5-59mp-jv5rHigh, 8.2DoS: crafted requests cause excessive CPU in App Router apps with Server Actions13.0.0 to 15.5.27, 16.0.0 to 16.4.015.5.28, 16.4.1None

The two React Server Components bugs also have upstream React advisories: GHSA-xqc2-xf4c-x3h3 for the typed-array RCE and GHSA-h3gv-c5rc-p453 for the DoS. Next.js ships its own compiled copy of react-server-dom-webpack and react-server-dom-turbopack inside the next package (I checked node_modules/next/dist/compiled), so upgrading next is what fixes a Next.js app, not bumping react alone.

Quick definitions#

TermWhat it means
RCERemote code execution: an attacker can run code on your server
DoSDenial of service: the server stops answering legitimate requests
GHSAA GitHub Security Advisory ID
sharpThe image library Next.js uses for Image Optimization; it bundles libvips and librsvg
glibcThe C library used by Debian, Ubuntu and node:*-slim images (Alpine uses musl instead)
Active / Maintenance LTSNext.js 16.4.x and 15.5.x, the two release lines that receive security fixes

TL;DR: how to patch Next.js now#

  1. Upgrade: npm install next@16.4.2 on 16.x (16.4.1 is the security release; 16.4.2 adds bug fixes) or npm install next@15.5.28 on 15.x.
  2. Check sharp: run npm ls next sharp and confirm sharp@0.35.5 or later. On 15.x, run npm update sharp if it still shows 0.34.x.
  3. Commit the lockfile, rebuild the image from scratch and redeploy.
  4. Verify the running container, not just your laptop.

Decision chart: check the installed next version, then the three advisories with their affected versions, exposure conditions and workarounds, and the fix of next 16.4.1 or 15.5.28 with sharp 0.35.5

Is my Next.js app affected?#

You are affected if your installed next is 16.0.0 through 16.4.0, or 15.5.27 and earlier, or if the sharp copy Next.js loads is older than 0.35.5. Which bugs reach you depends on features: use cache needs Cache Components, the DoS needs at least one Server Action, and the SVG bug needs glibc Linux.

Check the versions first:

bash
npm ls next sharp

Then match your app against each advisory:

  • use cache RCE (GHSA-673q-mjm6-r5xr). Only Next.js 16 apps using the App Router with Cache Components can be exposed, and the trigger is a use cache function that returns multiple typed arrays. The advisory still says to upgrade immediately even if your application does not have similar functions. New apps from create-next-app 16.4 have Cache Components on by default, as I covered in Next.js use cache explained.
  • SVG Image Optimization RCE (CVE-2026-96889). A memory bug in librsvg, which sharp uses to decode SVG, can lead to RCE when Next.js runs on glibc-based Linux. That covers most Debian and Ubuntu based Docker images and VPS installs. By default Next.js does not optimize SVG images; apps that set images.dangerouslyAllowSVG: true are the clearest exposure, but the advisory is not limited to that setting, so patch either way.
  • Server Actions DoS (GHSA-p3m5-59mp-jv5r). Any App Router app with at least one Server Action, on Next.js 13 through 15.5.27 or 16.0.0 through 16.4.0. Pages Router apps and apps without Server Actions are not vulnerable.

Why does npm audit say my app is safe?#

Because the advisory feed it reads may not list these issues yet. On October 17, 2026, I installed next@16.4.0, react and react-dom in an empty project and ran npm audit:

bash
$ npm audit --json | jq .metadata.vulnerabilities
{ "info": 0, "low": 0, "moderate": 0, "high": 0, "critical": 0, "total": 0 }

Zero findings on a version with two open critical advisories. Treat npm audit, Dependabot and similar scanners as a backstop here and check the versions yourself, or use the script below.

A script that checks your app against all three advisories#

I wrote this to check every app I run. It reads the installed next version, resolves sharp from Next.js's own folder (the copy the image optimizer actually loads), scans your source for use cache, use server and dangerouslyAllowSVG, and exits with code 1 if anything is unpatched, so you can drop it into CI. It has no dependencies.

js
// check-next-security.mjs: checks a Next.js app against the October 14, 2026 advisories.
// Usage: node check-next-security.mjs [projectDir]
import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs'
import { createRequire } from 'node:module'
import path from 'node:path'

const dir = path.resolve(process.argv[2] ?? '.')
const req = createRequire(path.join(dir, 'package.json'))
// Find node_modules/<pkg>/package.json the way Node would, without relying on "exports".
const version = (pkg, from = req) => {
  for (const base of from.resolve.paths(pkg) ?? []) {
    const file = path.join(base, pkg, 'package.json')
    if (existsSync(file)) return JSON.parse(readFileSync(file, 'utf8')).version
  }
  return null
}
const cmp = (a, b) => {
  const [x, y] = [a, b].map((v) => v.split('-')[0].split('.').map(Number))
  for (let i = 0; i < 3; i++) if (x[i] !== y[i]) return x[i] - y[i]
  return 0
}
const inRange = (v, lo, hi) => cmp(v, lo) >= 0 && cmp(v, hi) <= 0

// Scan source files for features the advisories depend on.
const src = []
const walk = (d) => {
  for (const name of readdirSync(d)) {
    if (['node_modules', '.next', '.git', 'out', 'dist'].includes(name)) continue
    const p = path.join(d, name)
    if (statSync(p).isDirectory()) walk(p)
    else if (/\.(m?[jt]sx?)$/.test(name)) src.push(readFileSync(p, 'utf8'))
  }
}
walk(dir)
const code = src.join('\n')
const uses = {
  useCache: /['"]use cache(: \w+)?['"]/.test(code),
  serverActions: /['"]use server['"]/.test(code),
  svgOptimizer: /dangerouslyAllowSVG\s*:\s*true/.test(code),
  nextOg: /from ['"]next\/og['"]/.test(code),
}

const next = version('next')
if (!next) { console.error('next is not installed in', dir); process.exit(2) }
// Resolve sharp from next's own folder, since that is the copy the image optimizer loads.
const nextPkg = (req.resolve.paths('next') ?? []).map((b) => path.join(b, 'next', 'package.json')).find(existsSync)
const sharp = version('sharp', createRequire(nextPkg))
const major = Number(next.split('.')[0])

const checks = [
  {
    id: 'GHSA-673q-mjm6-r5xr (critical): RCE in use cache returning typed arrays',
    vulnerable: inRange(next, '16.0.0', '16.4.0'),
    fix: 'upgrade next to 16.4.1+ (no workaround)',
    note: uses.useCache ? 'app uses "use cache"' : 'no "use cache" found, upgrade anyway',
  },
  {
    id: 'CVE-2026-96889 / GHSA-2464-fhr4-w9xw (critical): RCE via SVG in image optimization',
    vulnerable: sharp ? cmp(sharp, '0.35.5') < 0 : false,
    fix: 'sharp must be 0.35.5+ (npm update sharp), next 16.4.1+ or 15.5.28+',
    note: `sharp ${sharp ?? 'not installed'}` + (uses.svgOptimizer ? ', dangerouslyAllowSVG on' : '') + (uses.nextOg ? ', uses next/og' : ''),
  },
  {
    id: 'GHSA-p3m5-59mp-jv5r (high): DoS via Server Actions',
    vulnerable: inRange(next, '13.0.0', '15.5.27') || inRange(next, '16.0.0', '16.4.0'),
    fix: major >= 16 ? 'upgrade next to 16.4.1+' : 'upgrade next to 15.5.28+',
    note: uses.serverActions ? 'app defines Server Actions' : 'no "use server" found',
  },
]

console.log(`next ${next}, sharp ${sharp ?? 'not installed'} in ${dir}\n`)
let bad = 0
for (const c of checks) {
  if (c.vulnerable) bad++
  console.log(`${c.vulnerable ? 'VULNERABLE' : 'ok        '}  ${c.id}`)
  console.log(`            ${c.note}${c.vulnerable ? `\n            fix: ${c.fix}` : ''}`)
}
console.log(bad ? `\n${bad} issue(s) found. Patch, rebuild and redeploy.` : '\nAll three October 14, 2026 advisories are patched.')
process.exit(bad ? 1 : 0)

Run it from your project root with node check-next-security.mjs. This is the real output on a Next.js 16.4.0 app with one use cache function and one Server Action, before and after npm install next@16.4.2:

bash
$ node check-next-security.mjs
next 16.4.0, sharp 0.35.4 in /app

VULNERABLE  GHSA-673q-mjm6-r5xr (critical): RCE in use cache returning typed arrays
            app uses "use cache"
            fix: upgrade next to 16.4.1+ (no workaround)
VULNERABLE  CVE-2026-96889 / GHSA-2464-fhr4-w9xw (critical): RCE via SVG in image optimization
            sharp 0.35.4
            fix: sharp must be 0.35.5+ (npm update sharp), next 16.4.1+ or 15.5.28+
VULNERABLE  GHSA-p3m5-59mp-jv5r (high): DoS via Server Actions
            app defines Server Actions
            fix: upgrade next to 16.4.1+

3 issue(s) found. Patch, rebuild and redeploy.

$ npm install next@16.4.2 && node check-next-security.mjs
next 16.4.2, sharp 0.35.5 in /app

ok          GHSA-673q-mjm6-r5xr (critical): RCE in use cache returning typed arrays
            app uses "use cache"
ok          CVE-2026-96889 / GHSA-2464-fhr4-w9xw (critical): RCE via SVG in image optimization
            sharp 0.35.5
ok          GHSA-p3m5-59mp-jv5r (high): DoS via Server Actions
            app defines Server Actions

All three October 14, 2026 advisories are patched.

The script checks versions and source patterns; it is not an exploit test. A clean result means you are on patched versions, which is what the advisories ask for.

How do you upgrade Next.js 16 to the patched version?#

Install the latest 16.4 patch, then confirm sharp moved with it. Next.js 16.4.1 raised its sharp requirement to ^0.35.5 (16.4.0 accepted ^0.35.4; I read both from the npm registry), so npm has to upgrade sharp when you upgrade next.

bash
npm install next@16.4.2
npm ls next sharp

In my test, a project whose lockfile held next@16.4.0 and sharp@0.35.4 came out of npm install next@16.4.1 with sharp@0.35.5, as expected. Run the same check with pnpm why sharp or yarn why sharp if you use those package managers.

eslint-config-next should match your next version, so bump it in the same commit. If you have not moved to 16 yet, the version 16 upgrade guide covers the breaking changes; that is a bigger job than this patch, so patch 15.x first.

How do you patch Next.js 15 safely?#

Upgrade to 15.5.28, then check sharp separately, because upgrading next alone may not fix the SVG bug. Next.js 15.5.28 declares sharp as ^0.34.3 || ^0.35.5, so an existing lockfile that already resolved sharp 0.34.x still satisfies it, and npm keeps it.

This is what happened on a real project with next@15.5.27 and sharp@0.34.5 in the lockfile:

bash
$ npm install next@15.5.28
$ npm ls sharp
└─┬ next@15.5.28
  └── sharp@0.34.5        # still vulnerable

$ npm update sharp
$ npm ls sharp
└─┬ next@15.5.28
  └── sharp@0.35.5        # fixed

If sharp is a direct dependency in your package.json, run npm install sharp@0.35.5 instead. To force one version across a monorepo, add an override:

json
{
  "overrides": {
    "sharp": "0.35.5"
  }
}

pnpm uses pnpm.overrides and Yarn uses resolutions for the same job.

How do you patch a self-hosted Next.js app in Docker or Coolify?#

Update the lockfile, rebuild the image without reusing old layers, redeploy, then check the versions inside the running container. A dependency fix only protects you once the container that serves traffic contains it, and a Docker build that copies package-lock.json and runs npm ci installs exactly what the lockfile says.

Six-step patch flow for self-hosted Next.js: update deps, check the lockfile, commit it, rebuild the image, redeploy with Coolify or docker compose, and verify the versions inside the container

  1. Update and verify locally. npm install next@16.4.2, npm ls next sharp, run the checker.
  2. Commit package-lock.json. Without it, your build server resolves whatever it resolved last time.
  3. Rebuild the image. With the standalone output used in my production Next.js Dockerfile, next build copies sharp and its native libvips package into .next/standalone/node_modules. In my build that was @img/sharp-libvips-linux-x64, the glibc variant. An image built before the patch keeps the old sharp until you rebuild it.
  4. Redeploy. In Coolify, push the commit or click Redeploy. To skip cached layers for this one build, trigger a forced deploy, for example through the Coolify API with GET /api/v1/deploy?uuid=<app-uuid>&force=true. My self-host Next.js with Coolify guide covers the deploy setup. With plain Docker, run docker compose build --no-cache && docker compose up -d.
  5. Verify the running container. In a standalone image the app lives in /app, so:
bash
docker exec <container> node -e "console.log(require('/app/node_modules/next/package.json').version, require('/app/node_modules/sharp/package.json').version)"

Requiring the package.json files by absolute path works even though sharp 0.35.5 does not export ./package.json. I checked the same command against a standalone build of Next.js 16.4.2; it printed 0.35.5 16.4.2 for sharp and next. Adjust the path if your Dockerfile copies the app somewhere other than /app.

What if you cannot upgrade Next.js today?#

Only the SVG bug has an interim mitigation; the use cache RCE and the Server Actions DoS have no workaround, so plan the upgrade within hours, not weeks. In the meantime:

BugInterim stepSource
SVG / sharp RCEMake sure sharp is 0.35.5 or later, even without upgrading nextNext.js advisory
SVG / sharp RCEIn your own code that calls sharp, block SVG decoding with sharp.block({ operation: ['VipsForeignLoadSvg'] })sharp advisory
SVG / sharp RCETurn off images.dangerouslyAllowSVG if you do not need optimized SVGsImage docs
use cache RCENone. Upgrade.Next.js advisory
Server Actions DoSNone. Upgrade. Rate limits only reduce the blast radius.Next.js advisory

I tested the sharp.block call with sharp 0.35.5: before it, a small SVG converted to a 100-byte PNG; after it, the same call failed with Input buffer contains unsupported image format.

js
import sharp from 'sharp'

// Refuse to decode SVG input anywhere this sharp instance is used.
sharp.block({ operation: ['VipsForeignLoadSvg'] })

The sharp advisory adds one hardening note: whether the librsvg bug can reach code execution depends partly on the Node.js binary. It recommends a node built as a Position Independent Executable (PIE), notes that most Linux distribution packages already are, and warns that the official Node.js binaries are not.

How do you know whether you were attacked?#

The advisories publish no indicators of compromise and do not mention exploitation in the wild, so look for the side effects each bug would leave, and re-check the advisories for updates.

  • DoS: sustained 100% CPU on a Next.js process together with slow or failed requests, especially POST requests carrying a Next-Action header.
  • SVG RCE: unexpected requests to /_next/image with .svg sources, crashes of the Node.js process during image optimization, and new child processes or outbound connections from the container.
  • Any RCE: unknown files in the container filesystem, changed environment variables or secrets used from new IPs. If you find any of these, rotate secrets (database URLs, API keys, NEXT_SERVER_ACTIONS_ENCRYPTION_KEY) after patching.

Security habits that make the next patch faster#

This was an out-of-band release that landed eight days after 16.4.0 shipped on October 6. A few habits keep the next one to a ten-minute job:

  • Stay on an LTS line. Security fixes land on 16.4.x (Active LTS) and 15.5.x (Maintenance LTS).
  • Turn on upgrade nudges. Next.js 16.4 added experimental.agentUpgrade, whose default 'security' policy reminds you during next dev and next build when an upgrade fixes a known vulnerability in your installed version (Next.js 16.4 notes).
  • Run the checker in CI. Exit code 1 fails the build when a vulnerable version is installed.
  • Pin and commit lockfiles, then rebuild images from them so the running version is the one you reviewed.
  • Keep Server Actions small and authenticated. The DoS needs only one action to exist, but auth and input validation limit what any future bug can reach; see Server Actions vs Route Handlers.

Common mistakes when patching#

MistakeWhat happensFix
Upgrading react instead of nextNext.js keeps its bundled RSC runtimeUpgrade next
Upgrading 15.x to 15.5.28 and stoppingsharp 0.34.x can stay in the lockfilenpm update sharp, confirm 0.35.5+
Trusting npm auditIt reported 0 issues on unpatched 16.4.0Check versions or run the script
Not committing the lockfileCI or Coolify rebuilds the old versionsCommit package-lock.json
Rebuilding from a cached layerOld node_modules layer is reusedBuild once with no cache
Checking only the laptopProduction still runs the old imagedocker exec into the running container

Related: I packaged the checker script above as a reusable agent skill, so Claude Code, Cursor, Codex or Copilot can run the check and patch for you. See Agent Skills: how to write a SKILL.md.

Key takeaways#

  • The October 14, 2026 update fixes two critical RCEs (use cache typed arrays and SVG via sharp) and a high-severity Server Actions DoS.
  • Patched versions are Next.js 16.4.1+ and 15.5.28+, with sharp 0.35.5 or later.
  • On 15.x, upgrading next can leave sharp 0.34.x installed; run npm update sharp and verify.
  • npm audit reported nothing for unpatched next@16.4.0 on October 17, 2026, so check versions directly.
  • A self-hosted fix only counts after you rebuild the image, redeploy and verify the versions inside the running container.

Questions