Guide · Frontend
Next.js October 2026 Security Update Explained: Two RCEs and What to Upgrade
21 min readUpdated By Saket Bhatnagar
Researched and drafted with AI, reviewed and edited by Saket Bhatnagar.
In short
- This Next.js security update came out on 14 October 2026 as next 16.4.1 and 15.5.28. It fixes two critical remote code execution (RCE) bugs, where an attacker can make your server run their commands, and one high-severity bug.
- Bug one sits in React Server Components, React's way of running components on the server and streaming their output to the browser. It needs Next.js 16.0.0 to 16.4.0 with Cache Components and a 'use cache' function (a function whose result Next.js stores) returning several typed arrays.
- Bug two is a memory bug in librsvg, the SVG reader inside sharp, the image library Next.js 15 and 16 install to resize pictures. It affects glibc-based Linux such as Ubuntu, and sharp 0.35.5 fixes it.
- Bug three lets crafted requests to Server Actions, server functions that a form calls directly, burn CPU until the app stops answering. Upgrade next, confirm npm ls shows sharp 0.35.5 or later, then rebuild and redeploy.
- Beginners can stop after the section on which versions to install. Engineers get a tested lockfile trap that keeps a vulnerable sharp 0.34.5 under next 15.5.28, and proof that Next.js undoes a startup sharp.block, the switch that turns off SVG decoding. They also get why one bug scores 9.5 for Next.js but 8.9 for sharp on CVSS, the 0 to 10 severity scale.
What goes wrong when a framework's hidden dependencies have a security bug?
Your app can be open to attack even when every line you wrote is fine. This Next.js security update shows it: all three bugs live in upstream dependencies, the libraries Next.js pulls in for you.
You never imported librsvg or the React payload code yourself. They arrive with next, so a security fix only reaches you when the right versions land in your lockfile. A lockfile is the file, such as package-lock.json, that pins the exact version of every package.
Picture a common setup. A small web team at a tiffin subscription service in Pune runs a customer site on Next.js 16.3.8 with the App Router, Next.js's folder-based way of building pages. An older admin panel still runs Next.js 14.2.15. The setup is made up, but the advisories are real.
On 8 October 2026, the Next.js team announced a fix for 14 October covering two critical bugs and one high. The web team's first question was the reader's question too: which of our apps are exposed, and what exactly do we install?
Which words do you need before reading a security advisory?
You need six words. Each one comes back later in the guide.
- Advisory: a public notice naming a bug, the affected versions and the fixed versions. GitHub advisory IDs start with GHSA, and a CVE is a shared public ID for one bug.
- RCE, or remote code execution: an attacker on the internet makes your server run their commands. They can then read anything the server can read, such as payment keys.
- Memory bug: a mistake in low-level code where a program touches memory it should not. Attackers can sometimes steer this into running their own code.
- Denial of service: an attack that steals nothing but keeps the server too busy to answer real customers.
- CVSS: a 0 to 10 severity score. These advisories use version 4.0, where 9.0 to 10.0 counts as critical and 7.0 to 8.9 as high.
- Native code: code compiled straight to machine instructions, written in languages such as C or Rust. A memory bug there can do far more damage than a bug in JavaScript.
What is in the Next.js security update of 14 October 2026?
It is an out-of-band release, meaning an extra patch outside the normal schedule. It shipped next 16.4.1 for the Active LTS line and 15.5.28 for the Maintenance LTS line on 14 October 2026.
LTS means long-term support. In Next.js, the newest major version is Active LTS and gets features and fixes. The previous major is Maintenance LTS and gets only critical bug fixes and security fixes. Version 14.x is listed as unsupported.
The 8 October announcement said two of the three fixes had been postponed from the 30 September security release because of upstream coordination. The 30 September post had said one critical fix and one high fix were held back.
| Bug | Advisory IDs | Severity (CVSS 4.0) | Affected next versions | Fixed in |
|---|---|---|---|---|
| RCE when a 'use cache' function returns multiple typed arrays | GHSA-673q-mjm6-r5xr (Next.js), GHSA-xqc2-xf4c-x3h3 (React) | Critical, 9.5 | 16.0.0 to 16.4.0 | next 16.4.1 |
| RCE in the Image Optimization API when SVG files are used | CVE-2026-96889, GHSA-2464-fhr4-w9xw (Next.js), GHSA-wq5f-xc86-pv6w (sharp) | Critical, 9.5 (Next.js); high, 8.9 (sharp) | 10.0.0 to 15.5.27, and 16.x up to 16.4.0 (the advisory writes the 16.x range as above 16.0.0) | next 15.5.28 or 16.4.1, with sharp 0.35.5 |
| CPU exhaustion through Server Actions | GHSA-p3m5-59mp-jv5r (Next.js), GHSA-h3gv-c5rc-p453 (React) | High, 8.2 | 13.0.0 to 15.5.27, and 16.0.0 to 16.4.0 | next 15.5.28 or 16.4.1 |
The customer site on 16.3.8 is inside the version range of all three rows. Row one also needs Cache Components, and row three needs at least one Server Action. The admin panel on 14.2.15 sits in the version ranges of rows two and three, and no 14.x fix exists.
How does the 'use cache' bug let attackers run code on the server?
A crafted request can make the server run attacker code while React handles the data of a 'use cache' function that returns multiple typed arrays. No login is needed, according to the Next.js advisory.
What a 'use cache' function sends
React Server Components, or RSC, are components that run only on the server. Their output travels to the browser as an RSC payload, a streaming format that is mostly text but carries typed arrays as raw bytes. React encodes values into it on one side and decodes them on the other.
In Next.js 16, 'use cache' is a directive, a one-line marker at the top of an async function, that stores the function's result. It only works when cacheComponents, a setting in next.config, is set to true.
Why typed arrays matter
A typed array is a fixed-length list of raw numbers of one kind, such as Float32Array for decimals. The Next.js docs list TypedArrays and ArrayBuffers as allowed return values. Picture the customer site's weekly nutrition chart, returned as two typed arrays.
The React advisory says the bug affects only extremely rare cases where responses carry multiple typed arrays and an attacker-controlled value. As of 19 October 2026, neither advisory says which step fails, and this guide does not guess.
Where the 'use cache' bug sits
Drag to exploreNotice that the attacker never touches the team's own code. The weak spot is shared React payload code, which is why the fix arrives as a React and Next.js version bump.
Diagram connections:
- Crafted request to Next.js App Router (HTTP request)
- Next.js App Router to 'use cache' function (Calls the cached function)
- 'use cache' function to RSC payload code (Result with typed arrays)
- RSC payload code to Attacker code runs (Unpatched 19.0.0 to 19.3.0)
- Crafted request: From the internet, no login needed
- Next.js App Router: Receives the request on the team's server
- 'use cache' function: Returns two typed arrays, Cache Components on
- RSC payload code: react-server-dom code: where the bug sits
- Attacker code runs: Can read environment variables and secrets
How does an SVG image lead to remote code execution through sharp?
A memory bug in librsvg, the native library that reads SVG files, can lead to code execution when Next.js runs on glibc-based Linux. The sharp advisory lists CWE-416, the catalogue number for a use-after-free bug.
The path is long. The Image Optimization API answers requests at /_next/image and resizes pictures on the fly. It calls sharp, a Node.js image library built on libvips, a native image engine. libvips uses librsvg to read SVG files.
The image path that reaches librsvg
Drag to exploreNotice where JavaScript ends. Next.js and sharp's wrapper are JavaScript; libvips and librsvg are native code, which is where a memory bug can turn into code execution. The advisories do not say how SVG input reaches librsvg; this shows only which parts are involved.
Diagram connections:
- Visitor's browser to Image Optimization API (GET /_next/image)
- Image Optimization API to sharp (Node.js) (Resize request)
- sharp (Node.js) to libvips (Native call)
- libvips to librsvg (Its SVG reader)
- Visitor's browser: Asks for a resized image
- Image Optimization API: The /_next/image endpoint in Next.js
- sharp (Node.js): Image library next installs as optional dependency
- libvips: Native image engine bundled with sharp
- librsvg: SVG reader used by libvips: fixed in 2.63.2
Use-after-free, in one picture
Use-after-free means code keeps using a piece of memory after handing it back. Think of a hotel guest who keeps the room key after checkout. The room is the memory, checkout is freeing it, and the next guest is new data.
If the old key still opens the door, the old guest can rearrange the new guest's room. An attacker who controls what moves in next can sometimes turn that into running their own code.
Where the picture breaks: a hotel would notice two guests. Code in C, or Rust code marked unsafe, has no front desk checking each access as it runs. A stale access looks like any other and raises no alarm.
What the docs say and what the advisory says
glibc is the standard C library on most Linux systems, such as Ubuntu and Debian. Picture the customer site running on an Ubuntu server, with partner logos stored as SVG files.
The Next.js Image docs say SVG is not optimised by default, and a src ending in .svg is served unoptimised automatically. The advisory, though, lists every version from 10.0.0 and names no setting that makes you safe.
The source fits that warning. In next 15.5.27, 15.5.28, 16.4.0 and 16.4.1, the image code blocks all of sharp's file readers, then switches a short list back on.
The SVG reader, VipsForeignLoadSvg, is on that list. As of 19 October 2026, neither advisory says how SVG input reaches it, and this guide does not guess.
What is the Server Actions denial-of-service bug?
Crafted requests can push CPU use so high that the process stops serving other requests. Next.js apps using the App Router with at least one Server Action are exposed. Nothing is stolen, but the site goes quiet.
A Server Action is a server function that a form or button calls directly, like the customer site's Pause my tiffin button. Node.js runs your JavaScript on one main thread, the event loop. While it is busy with one request, other requests wait.
The React advisory says the attack can cause out-of-memory errors as well as heavy CPU use. Pages Router apps, and App Router apps without Server Actions, are not affected. Neither advisory offers a workaround.
Which Next.js and sharp versions should you install in October 2026?
On 16.x, install next 16.4.1 or later; 16.4.2 is the latest as of 19 October 2026. On 15.x, install 15.5.28, then confirm sharp is 0.35.5 or later. sharp 0.35.5 declares support for Node.js 20.9.0 or later.
Next.js ships its own built-in copy of the React payload code inside the next package, so for a Next.js app the next upgrade brings the React fix.
If package.json also lists react-server-dom-webpack or -turbopack directly, for another RSC setup, move them to 19.0.9, 19.1.10, 19.2.9 or 19.3.1, matching your line. react-server-dom-parcel has no 19.0 releases on npm, so its fixed versions are 19.1.10, 19.2.9 and 19.3.1.
The Next.js post offers no patch for 14.x or older. The team's admin panel needs a move to 15.5.28 or 16.x, and the Server Actions bug stays open until then.
One date matters for 15.x. The support policy keeps a major in Maintenance LTS for two years after its first release, and 15.x first shipped on 21 October 2024.
Read literally, that puts the end of 15.x support around 21 October 2026, two days after this guide's date. Treat 15.5.28 as a stopgap and plan the move to 16.x.
What to install, by situation
Drag to exploreNotice that every path runs through the sharp check. Upgrading next alone is not the end of the job on any line.
Diagram connections:
- Which next line? to next 16.4.1 or later (16.x)
- Which next line? to next 15.5.28 (15.x)
- Which next line? to Plan a move off 14.x (14.x or older)
- next 16.4.1 or later to Check sharp 0.35.5+ (Then)
- next 15.5.28 to Check sharp 0.35.5+ (Then)
- Plan a move off 14.x to Check sharp 0.35.5+ (If sharp is installed)
- Check sharp 0.35.5+ to Rebuild and redeploy (Then)
- Which next line?: Check with npm ls next
- next 16.4.1 or later: Fixes all three bugs; 16.4.2 is latest
- next 15.5.28: Fixes the SVG and Server Actions bugs
- Plan a move off 14.x: No 14.x fix; sharp 0.35.5 only as a stopgap
- Check sharp 0.35.5+: npm ls sharp; Node.js 20.9.0 or later
- Rebuild and redeploy: Every server and container image
List what you run
Run npm ls next sharp in every app and every Docker image build. Write down each next line and each sharp version.
Install the fixed next
Run npm install [email protected] or later on 16.x, or npm install [email protected] on 15.x. Plan the move for anything older.
Confirm sharp
Make sure npm ls shows sharp 0.35.5 or later. If it does not, run npm update sharp and remove any old pin or override.
Bump direct RSC packages
If package.json lists react-server-dom packages, move them to the fixed version for your line.
Rebuild and redeploy everywhere
Build fresh images and deploy to every server, then run the check below on the deployed build.
You can check the result in two commands. The second prints the librsvg version that sharp bundles; the fixed value is 2.63.2.
npm ls next sharp
node -e "console.log(require('sharp').versions.rsvg)"
# Expected on a fixed 16.x app (tested 19 October 2026):
# `-- [email protected]
# `-- [email protected]
# 2.63.2If the second command prints undefined, sharp is using a libvips installed on the system, and you check that system's librsvg instead. The command also assumes npm placed sharp at the top of node_modules, as in every test here.
Beginners can stop here: you know what broke, what to install and how to check it.
Why can upgrading to Next.js 15.5.28 leave sharp vulnerable?
Because 15.5.28 still accepts sharp 0.34, and npm keeps a locked version that still fits. The Next.js post says patched versions make package managers supply a fixed sharp. That holds on a fresh install, not always on an upgrade.
The naive plan is to run npm install [email protected] and move on. Pause and predict: the lockfile already holds sharp 0.34.5. Which sharp do you have after the upgrade?
We tested it with npm 10.9.4 on Node.js 22.22.0. The project's lockfile started on next 15.5.27 with sharp 0.34.5. After npm install [email protected], npm ls still showed sharp 0.34.5, which bundles librsvg 2.61.2.
| Starting point | Command | sharp after | librsvg |
|---|---|---|---|
| Fresh project | npm install [email protected] | 0.35.5 | 2.63.2 |
| Lockfile with next 15.5.27 and sharp 0.34.5 | npm install [email protected] | 0.34.5 (still vulnerable) | 2.61.2 |
| The same project, one step later | npm update sharp | 0.35.5 | 2.63.2 |
| Lockfile with next 16.3.8 and sharp 0.35.4 | npm install [email protected] | 0.35.5 | 2.63.2 |
What just happened? next 15.5.28 lists sharp as an optional dependency with the range 0.34.3 or later in 0.34, or 0.35.5 or later in 0.35. A locked 0.34.5 satisfies that range, so npm left it alone.
next 16.4.1 asks for sharp 0.35.5 or later in 0.35, so the old lock no longer fits and npm moved it. That one range explains the different results on the two lines.
Node.js matters here too. sharp 0.35.5 declares Node.js 20.9.0 or later, while next 15.5.28 still allows Node.js 18.18. A 15.x app on Node.js 18 is outside sharp's supported range, so plan the Node.js upgrade with the sharp fix.
This script reads package-lock.json and flags every copy of sharp below 0.35.5. It exits with code 1 when it finds one, so it can fail a CI job, the automated checks that run on each change.
import json
import sys
SHARP_FIXED = (0, 35, 5)
def parse(version):
core = version.split("-")[0]
return tuple(int(part) for part in core.split("."))
lock_path = sys.argv[1] if len(sys.argv) > 1 else "package-lock.json"
with open(lock_path) as f:
packages = json.load(f)["packages"]
bad = 0
for path, info in packages.items():
if not path.endswith("node_modules/sharp"):
continue
version = info.get("version", "0.0.0")
if parse(version) < SHARP_FIXED:
bad += 1
print(path, version, "VULNERABLE: needs 0.35.5 or later")
else:
print(path, version, "ok")
sys.exit(1 if bad else 0)On the trapped lockfile it printed node_modules/sharp 0.34.5 VULNERABLE: needs 0.35.5 or later, and exited 1. On a fresh 16.4.1 lockfile it printed node_modules/sharp 0.35.5 ok. It reads lockfiles from npm 7 or later, not pnpm or Yarn ones.
What workarounds exist if you cannot upgrade Next.js today?
For the 'use cache' bug and the Server Actions bug, none: both advisories say upgrade. For the SVG bug, the Next.js post's workaround is making sure Next.js uses sharp 0.35.5 or later. The sharp advisory adds two more.
- Block SVG decoding: call sharp.block with the operation VipsForeignLoadSvg, so SVG input fails instead of reaching librsvg. The block function exists from sharp 0.32.4.
- Run a PIE build of node: PIE, or position-independent executable, lets the operating system load the program at a different memory address each run. The sharp advisory says this reduces RCE risk and notes official Node.js binaries are not PIE builds.
If sharp uses a librsvg installed on the system instead of its bundled copy, the fix is librsvg 2.63.2 or later, per the sharp advisory.
Next.js undoes the sharp.block workaround
On next 15.5.28 and 16.4.1, a startup sharp.block call did not survive in our test. Next.js's image code unblocks VipsForeignLoadSvg the first time it loads sharp, and both share one sharp module.
We blocked the SVG reader, confirmed a harmless 10 by 10 pixel SVG failed to decode, then let Next.js set up sharp as its image code does. The same SVG then decoded again. The unblock call is also in the 15.5.27 and 16.4.0 source.
So on 15.x and 16.x, upgrading sharp is the workaround that holds. On 14.2.35, Next.js's image code does not call block or unblock, so a block call stays in force there.
What 14.x apps should check
Next.js 14 does not install sharp for you; it uses sharp only if you added it, or if the NEXT_SHARP_PATH environment variable points to a copy. npm ls sharp does not see such a copy, so check its version too. The advisory still lists 14.x as affected without explaining further, so treat it as affected.
If a 14.x app has sharp, install sharp 0.35.5 as a stopgap. sharp 0.35.5 declares Node.js 20.9.0 or later, while next 14.2.35 still allows Node.js 18.17, so check Node.js first. In a smoke test, next 14.2.35 with sharp 0.35.5 on Node.js 22 resized a 400 by 300 pixel PNG to a 64 by 48 pixel WebP. One test is not a support promise.
Why is CVE-2026-96889 scored 9.5 by Next.js but 8.9 for sharp?
Each advisory scores the same flaw from its own point of view, and only one metric differs. The Next.js advisory says 9.5, critical. The sharp advisory on OSV, an open vulnerability database, says 8.9, high.
The difference is the attack vector, AV. Next.js uses AV:N, network: in the CVSS spec, the vulnerable system is bound to the network stack, as an image endpoint is.
sharp uses AV:L, local: the vulnerable system is not bound to the network stack, which fits a library with no network port of its own. Neither advisory explains its choice.
Both vectors also carry AT:P, attack requirements present. The CVSS spec uses it when an attack depends on specific deployment and execution conditions being present. As of 19 October 2026, neither advisory says which conditions it means.
You can check the maths yourself. The open-source cvss package for Python, version 3.6, computes 9.5 for the Next.js vector and 8.9 for the sharp vector. It also reproduces 9.5 for the 'use cache' bug and 8.2 for the Server Actions bug.
Is this the first remote code execution flaw in React Server Components?
No. On 3 December 2025, React disclosed CVE-2025-55182, an unauthenticated RCE in the same react-server-dom packages. React rated it CVSS 10.0 and traced it to how React decodes payloads sent to Server Function endpoints.
As of its 26 January 2026 update, that post tells apps on 13.3 and later 13.x, and 14.x, to install next 14.2.35. The team's 14.2.15 admin panel had missed that round too.
The pattern is where risk lives: code that decodes rich data arriving in requests, and native code that parses files. Both of this month's RCEs sit in one of those two places.
How do you explain the Next.js October 2026 security update in a system design interview?
Tell it as a story about dependency risk. Interviewers listen for where untrusted input meets risky code, and how you would roll a fix out across many services.
Name the three bugs
Two critical RCEs, one in RSC payload handling and one in SVG decoding under sharp, plus a high-severity Server Actions CPU denial of service.
Point to the boundaries
Both RCEs sit where untrusted input meets code that decodes RSC payloads or parses files in native code.
Explain the dependency of a dependency
The bugs were upstream in React and librsvg. A framework upgrade fixes them only if the lockfile actually resolves the fixed versions.
Describe the rollout
Inventory every app, upgrade, verify the resolved sharp and librsvg versions, then redeploy. Add a CI check so an old lock cannot come back.
Add defence in depth
Mention PIE builds, least-privilege servers that hold few secrets, and rotating secrets if you see signs of a breach.
Questions people ask
- Do I need to upgrade if my app has no 'use cache' functions?
- Yes. The Next.js advisory says to upgrade even if your app has no such functions. The same release also fixes the SVG image bug and the Server Actions denial of service. Those reach many more apps, including ones that never turned on Cache Components.
- Is my app safe if it runs on Alpine Linux?
- Not fully. The SVG advisories name glibc-based Linux, and Alpine is built around a different C library called musl. The other two bugs do not depend on the operating system, so you still need the upgrade. Update sharp on Alpine too, since the fix costs little.
- Does upgrading next also upgrade sharp?
- On 16.x it did in our tests, because 16.4.1 asks for sharp 0.35.5 or later. On 15.x, not always: 15.5.28 still accepts sharp 0.34, and npm kept a locked 0.34.5. Run npm ls sharp, then npm update sharp if needed, on Node.js 20.9.0 or later.
- What if I am still on Next.js 14?
- There is no patched 14.x release, because the post ships fixes only for the 15.5 and 16.4 lines. Plan a move to 15.5.28 or 16.x. As a stopgap, update sharp to 0.35.5 on Node.js 20.9.0 or later if the app uses it, or block SVG decoding. The Server Actions bug stays open until you move.
- Are Pages Router apps affected?
- Partly. The Server Actions bug skips Pages Router apps, and the 'use cache' RCE needs the App Router with Cache Components. The SVG bug sits in the Image Optimization API, which both routers use, so Pages Router apps still need the fix.
- Should I rotate secrets after patching?
- Rotate them if you see signs of compromise, such as odd requests, crashes or unknown processes before you patched. If you do, treat every key in the server's environment variables as exposed, because an RCE gives an attacker whatever the server can read.
Sources and further reading
- Next.js Security Update for Upstream Vulnerabilities (Next.js blog, 14 October 2026)
- Upcoming Next.js Security Update for Upstream Vulnerabilities (Next.js blog, 8 October 2026)
- September 2026 Security Release (Next.js blog, 30 September 2026)
- GHSA-673q-mjm6-r5xr: RCE in use cache functions returning typed arrays (Next.js advisory)
- GHSA-xqc2-xf4c-x3h3: Unauthenticated RCE in React Server Components (React advisory)
- GHSA-2464-fhr4-w9xw: RCE in Image Optimization API when SVG files are used (Next.js advisory)
- GHSA-wq5f-xc86-pv6w: sharp, vulnerability in librsvg dependency CVE-2026-96889 (OSV)
- GHSA-p3m5-59mp-jv5r: Denial of Service in App Router using Server Actions (Next.js advisory)
- GHSA-h3gv-c5rc-p453: Denial of Service in Server Functions (React advisory)
- Next.js support policy (Active LTS and Maintenance LTS)
- use cache directive, serialisation and cacheComponents (Next.js docs)
- Image component, dangerouslyAllowSVG section (Next.js docs)
- Don't Block the Event Loop (or the Worker Pool) (Node.js docs)
- About Alpine Linux: built around musl libc and busybox (alpinelinux.org)
- CVSS v4.0 Specification Document (FIRST)
- Critical Security Vulnerability in React Server Components (React blog, 3 December 2025)