The Next.js team published its scheduled November security release on November 3, 2026, a week after the pre-announcement. Sebastian Silbermann and Jamiboy Mohammad shipped fixes in v16.4.5 (Active LTS) and v15.5.29 (Maintenance LTS). The release covers seven issues: one high, six medium.
npm install [email protected] # 16.x
npm install [email protected] # 15.5.x
Four of the seven sit in caching code. If you turned on Cache Components and read root parameters such as a tenant ID inside use cache functions, read the next section before anything else.
The seven issues
| Severity | Advisory | Issue |
|---|---|---|
| High | GHSA-mfr8-8qww-v76h | Cross-tenant cache disclosure when unstable_cache and use cache combine |
| Medium | GHSA-vc7v-qv4w-wrv8 | Nested use cache functions leak across root-parameter values |
| Medium | GHSA-rhh4-g77r-r9qj | Distinct binary arguments produce the same cache key |
| Medium | none listed | Shared shell cache poisoning under next start |
| Medium | GHSA-pc58-hwjq-p385 | Stale compressed framing on forwarded Response objects |
| Medium | GHSA-f3mh-rxg3-f5g2 | Cookie values exposed in x-middleware-set-cookie on Edge routes |
| Medium | GHSA-7qx7-33qx-rqx2 | AVIF misclassification bypasses dangerouslyAllowSVG: false |
Cache Components and tenants
The high-severity bug needs three things: Cache Components enabled, a public use cache function that reads a root parameter, and code that calls that function on its own and from inside unstable_cache. During a cold cache fill, a concurrent call through unstable_cache can pick up another request's result without checking its root parameters. Next.js then stores that result and serves it to later callers with the same arguments until you revalidate the entry or the cache evicts it.
A sketch of the risky shape:
// app/[tenant]/lib/data.ts
export async function getInvoices() {
"use cache";
const tenant = await currentTenant(); // your helper that reads the [tenant] root param
return db.invoices.findMany({ where: { tenant } });
}
// Somewhere else, the same function wrapped again
const getInvoicesLegacy = unstable_cache(() => getInvoices(), ["invoices"]);
If your root parameter separates customers, a customer can see another customer's data. The second medium bug hits the same boundary from another angle. An inner cached function reads a root parameter and returns an early value plus a slower async one, and the outer function finishes without awaiting the slow part. Next.js can store the outer entry before it records the inner function's root-parameter dependencies.
The third caching bug concerns binary arguments. If you pass a Uint8Array or similar into a use cache function to tell users apart, two different values can map to the same cache identity. One user can then receive another's cached result, or plant their own result for someone else.
Self-hosted apps
Two issues apply when you run next start yourself.
The shell-poisoning bug needs Cache Components on, Partial Prefetching off or unset, and a specific route shape: a prerenderable dynamic parameter requested with a value the build didn't generate, two deeper parameters that never prerender, a blocking fallback shell, and a layout that reads the shallower of those deeper parameters inside Suspense. One unauthenticated request with a crafted URL can then store request-specific values in a shell other URLs share, producing wrong pages or sticky 404s.
The response-framing bug hits apps that return an attacker-controlled fetched Response unchanged. Next.js forwarded decompressed bytes with the original compressed framing headers. Behind an HTTP/1.1 proxy that queues pipelined requests on a shared backend connection, responses can land on the wrong client. The advisory says it "does not apply to every reverse-proxy configuration."
Edge cookies and SVG
On Edge Route Handlers and Pages Router Edge API routes, NextResponse.cookies.set() also wrote the serialized cookie into x-middleware-set-cookie. Same-origin JavaScript can read that header, so HttpOnly stopped protecting the value. Exploiting it needs attacker JavaScript on your origin. Node.js Route Handlers and cookies().set() weren't affected in the reproduction.
The image optimizer bug lets an image from a permitted source pass as AVIF, skip dangerouslyAllowSVG: false, and reach an SVG decoder anyway. It requires a native backend that decodes SVG. The advisory shows no XSS or RCE from it. The risk is wider exposure to SVG parser bugs and resource exhaustion.
This week
- Bump to
[email protected]or[email protected]and redeploy. - Grep for
unstable_cache(and check whether any wrapped function contains"use cache"and reads root params. A codebase halfway through a move fromunstable_cachetouse cacheis the likeliest place to find it. - Search
use cachefunctions for binary arguments that carry user or account identity. - If you self-host behind an HTTP/1.1 proxy with request pipelining, check whether any route proxies a fetched
Responsestraight through. - After the upgrade, revalidate or purge entries from the affected functions. A leaked or poisoned entry keeps serving until you do.
Volodymyr Chornous

