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

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](https://nextjs.org/blog/nextjs-security-update-october-14-2026). 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.

| Advisory | Severity | What it is | Affected `next` versions | Fixed in | Workaround |
| --- | --- | --- | --- | --- | --- |
| [GHSA-673q-mjm6-r5xr](https://github.com/vercel/next.js/security/advisories/GHSA-673q-mjm6-r5xr) | Critical, 9.5 | RCE in `use cache` functions that return multiple typed arrays | 16.0.0 to 16.4.0 | 16.4.1 | None |
| [CVE-2026-96889 / GHSA-2464-fhr4-w9xw](https://github.com/vercel/next.js/security/advisories/GHSA-2464-fhr4-w9xw) | Critical, 9.5 | RCE in the Image Optimization API with SVG, via `sharp`'s librsvg, on glibc Linux | 10.0.0 to 15.5.27, 16.0.0 to 16.4.0 | 15.5.28, 16.4.1 | `sharp` 0.35.5 or later |
| [GHSA-p3m5-59mp-jv5r](https://github.com/vercel/next.js/security/advisories/GHSA-p3m5-59mp-jv5r) | High, 8.2 | DoS: crafted requests cause excessive CPU in App Router apps with Server Actions | 13.0.0 to 15.5.27, 16.0.0 to 16.4.0 | 15.5.28, 16.4.1 | None |

The two React Server Components bugs also have upstream React advisories: [GHSA-xqc2-xf4c-x3h3](https://github.com/facebook/react/security/advisories/GHSA-xqc2-xf4c-x3h3) for the typed-array RCE and [GHSA-h3gv-c5rc-p453](https://github.com/facebook/react/security/advisories/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

| Term | What it means |
| --- | --- |
| RCE | Remote code execution: an attacker can run code on your server |
| DoS | Denial of service: the server stops answering legitimate requests |
| GHSA | A GitHub Security Advisory ID |
| `sharp` | The image library Next.js uses for Image Optimization; it bundles libvips and librsvg |
| glibc | The C library used by Debian, Ubuntu and `node:*-slim` images (Alpine uses musl instead) |
| Active / Maintenance LTS | Next.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](https://res.cloudinary.com/wasicloudinary/image/upload/v1792242673/fabwaseem/blog/nextjs-security-update-october-2026/diagram-affected.jpg)

## 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](https://www.fabwaseem.com/blog/nextjs-use-cache).
- **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](https://nextjs.org/docs/app/guides/upgrading/version-16) 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](https://res.cloudinary.com/wasicloudinary/image/upload/v1792242674/fabwaseem/blog/nextjs-security-update-october-2026/diagram-patch-flow.jpg)

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](https://www.fabwaseem.com/blog/nextjs-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](https://www.fabwaseem.com/blog/self-host-nextjs-with-coolify) 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:

| Bug | Interim step | Source |
| --- | --- | --- |
| SVG / `sharp` RCE | Make sure `sharp` is 0.35.5 or later, even without upgrading `next` | [Next.js advisory](https://github.com/vercel/next.js/security/advisories/GHSA-2464-fhr4-w9xw) |
| SVG / `sharp` RCE | In your own code that calls `sharp`, block SVG decoding with `sharp.block({ operation: ['VipsForeignLoadSvg'] })` | [sharp advisory](https://github.com/lovell/sharp/security/advisories/GHSA-wq5f-xc86-pv6w) |
| SVG / `sharp` RCE | Turn off `images.dangerouslyAllowSVG` if you do not need optimized SVGs | [Image docs](https://nextjs.org/docs/app/api-reference/components/image) |
| `use cache` RCE | None. Upgrade. | Next.js advisory |
| Server Actions DoS | None. 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](https://nextjs.org/blog/next-16-4)).
- **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](https://www.fabwaseem.com/blog/server-actions-vs-route-handlers).

## Common mistakes when patching

| Mistake | What happens | Fix |
| --- | --- | --- |
| Upgrading `react` instead of `next` | Next.js keeps its bundled RSC runtime | Upgrade `next` |
| Upgrading 15.x to 15.5.28 and stopping | `sharp` 0.34.x can stay in the lockfile | `npm update sharp`, confirm 0.35.5+ |
| Trusting `npm audit` | It reported 0 issues on unpatched 16.4.0 | Check versions or run the script |
| Not committing the lockfile | CI or Coolify rebuilds the old versions | Commit `package-lock.json` |
| Rebuilding from a cached layer | Old `node_modules` layer is reused | Build once with no cache |
| Checking only the laptop | Production still runs the old image | `docker 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](https://www.fabwaseem.com/blog/agent-skills).

**Related:** running an MCP server next to your Next.js app? [MCP security in 2026](https://www.fabwaseem.com/blog/mcp-security) covers this month's MCP SDK OAuth advisories and how to fix them.

## 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.
