Cybersecurity

Next.js Shipped Seven Advisories and Six of Them Are the Cache

The November 2026 Next.js security release patches seven issues, and six live in the new Cache Components layer, the feature meant to make your app faster by remembering more. Three hit self-hosted next start specifically: the ones Vercel's own platform quietly absorbs.

lines of HTML code on a screen
Photo by Florian Olivo / Unsplash

A cache is a promise that two requests for the same thing can share one answer. The entire value of it is reuse — compute once, serve many. The entire danger of it is the word "same." Get the definition of "same" slightly wrong and you aren't sharing a cached page, you're handing one tenant's data to another, because the cache can't tell them apart.

The November 2026 Next.js security release is, almost in its entirety, a catalogue of ways to get "same" wrong. Seven advisories shipped on 3 November, patched in 16.4.5 (Active LTS) and 15.5.29 (Maintenance LTS). Six of the seven are in caching. Four are in one specific feature: Cache Components and its use cache directive. The mechanism in every one of those four is the same shape — content computed for one tenant, one user, or one locale gets served to a request that should have gotten its own.

And if you self-host, three of the seven are aimed at you specifically. They require next start — your own server, your own Node process — and they are the ones a platform like Vercel absorbs on your behalf without you ever filing a ticket. Self-hosting Next.js is a legitimate and common choice; this release is a reminder that it moves a category of responsibility onto you that the hosted path keeps.

The Numbers, and a Severity Note

Here is the whole release, with CVE IDs, CVSS 4.0 scores, and where each one bites. I have grouped it by what the SudoSecurity reader actually needs: which of these follow you onto your own server.

Advisory CVE CVSS What it is Self-hosted only?
GHSA-mfr8-8qww-v76h CVE-2026-119790 6.3 Cross-tenant cache disclosure (unstable_cache + use cache) No
GHSA-vc7v-qv4w-wrv8 CVE-2026-119351 6.3 Cross-root-parameter disclosure in nested use cache No
GHSA-rhh4-g77r-r9qj CVE-2026-119349 6.3 Cross-user disclosure via binary use cache arguments No
GHSA-vvgp-ww4w-46vf CVE-2026-119350 6.3 Shared shell cache poisoning Yes — next start
GHSA-pc58-hwjq-p385 CVE-2026-119348 6.3 Cross-client response injection via stale compression framing Yes
GHSA-7qx7-33qx-rqx2 CVE-2026-119347 6.9 SVG rejection bypass in Image Optimization Yes
GHSA-f3mh-rxg3-f5g2 CVE-2026-119346 6.0 HttpOnly cookie exposure via internal Edge header No

One wrinkle worth naming before the detail: Vercel's own blog post labels the lead advisory, the cross-tenant cache leak, High Severity in its prose, while its CVSS 4.0 base score is 6.3 — Medium. That's not a contradiction so much as two instruments measuring two things. The prose reacts to the impact: one tenant reading another's data is a serious phrase in any SaaS. The vector prices in how narrow the preconditions are. When a vendor's adjective and its number disagree, read both — the adjective tells you how bad it is when it happens, the number tells you how often the stars align. Here the stars need Cache Components turned on, a specific call pattern, and a cold cache, which is why a real-world-alarming outcome scores in the sixes.

The Four Faces of One Mistake

The use cache advisories are worth reading together, because individually they look like four bugs and together they look like one feature learning what "cache key" has to mean. Vercel's descriptions are precise, so I am quoting the mechanisms rather than paraphrasing them into mush.

Cross-tenant disclosure (CVE-2026-119790). The cache key forgot the tenant during a race. From the advisory:

During a cold cache fill, a concurrent call through unstable_cache can receive another request's result without checking its root parameters. That result can then be stored and served to later callers with the same arguments until the entry is revalidated or evicted.

A "root parameter" here is the thing that separates tenants — a workspace ID, an account slug, a locale. The bug is a cold-cache race: two requests arrive before the entry exists, one fills it, and the other receives the first one's result without its own tenant check being applied. Worse, that mis-attributed result then gets stored, so the leak is not a one-time race — it persists to every later caller until the entry expires. A transient timing bug becomes a durable poisoning.

Nested disclosure (CVE-2026-119351). When one use cache function wraps another, the outer entry could be finalized before the inner function had recorded which root parameters it depended on:

The outer entry can be stored before the inner function's root-parameter dependencies are recorded. This can disclose tenant-, site-, or locale-specific content across the corresponding routing boundary.

The dependency tracking and the cache write raced each other, and the write won. The cache recorded "this is reusable" before it finished learning "reusable for whom."

Binary-argument collision (CVE-2026-119349). Two different arguments produced the same cache identity:

Distinct binary arguments passed to a use cache function can produce the same cache identity. If an application uses those arguments to distinguish users or accounts... a caller can receive another user's cached result.

This is a hashing problem, not a race: the function that turns arguments into a cache key collapsed distinct binary inputs to one key. If you were passing a user token or an account handle as a binary argument expecting it to separate cache entries, it did not.

Put the three together and the pattern is unmistakable. A cache key is a claim that two things are interchangeable, and each of these is a different way the claim was made too early, too loosely, or too eagerly. The feature is new; use cache and Cache Components are recent additions. This is what the first serious security pass on a new caching primitive tends to find — not that caching is wrong, but that the identity function underneath it is the hardest part to get right.

We recommend reading npm Dependency Security Before CI: Where Trust Decisions Actually Happen to continue reading our selection of content. A framework's caching layer is a dependency you did not write making correctness decisions on your behalf, which is the same trust handoff at a different layer.

npm Dependency Security Before CI: Where Trust Decisions Actually Happen The trust boundary in a modern build is the dependency you inherited, not the code you wrote. SudoSecurity

The Three That Follow You Home

If you deploy to Vercel, the four cache bugs above still apply, because they're in the framework, not the platform. But the next three are where self-hosting changes your exposure. They require your own next start process and the infrastructure you put around it.

Shared shell cache poisoning (CVE-2026-119350), self-hosted next start. This is the one that is most clearly a you-problem. An unauthenticated request can poison a page shell that other URLs reuse:

A crafted URL can cause request-specific values to be stored in a shell used by other URLs, resulting in incorrect server-rendered content or persistent 404 responses.

The preconditions are specific — Cache Components enabled, Partial Prefetching disabled or unset, and a particular route shape with a dynamic parameter requested with a value not generated at build time — but the outcome is a cache-poisoning primitive reachable without authentication. "Persistent 404 responses" is a denial-of-service you serve to yourself: an attacker pins a page into a not-found state for everyone. Build-generated values and configurations with Partial Prefetching enabled were not affected in Vercel's tests, which is itself the mitigation hint.

Cross-client response injection (CVE-2026-119348), self-hosted. This one needs a reverse proxy, which means it needs the exact setup a self-hoster builds by hand:

Self-hosted applications that return an attacker-controlled fetched Response unchanged can forward decompressed body bytes with the original compressed response's framing headers. Behind an HTTP/1.1 reverse proxy that queues pipelined requests on a shared backend connection, this mismatch can cause responses to be assigned to the wrong clients.

The framing headers describe a compressed body; the bytes are decompressed; the lengths disagree; and on a shared keep-alive connection behind an HTTP/1.1 proxy, the desync hands one client another client's response. This is request-smuggling's quieter cousin, and it exists only because you own the proxy in front of your Node process. A managed platform terminates and re-frames responses in a layer you never see. The fix is also partly in your hands: do not return an upstream Response object unchanged, and prefer HTTP/2 to the backend where you can.

SVG bypass in Image Optimization (CVE-2026-119347, the highest score at 6.9), self-hosted. You told Next.js not to process SVGs, and an attacker got one processed anyway:

An attacker-controlled image from a permitted source can be misclassified as AVIF and bypass images.dangerouslyAllowSVG: false. The image optimization backend can then identify and decode the original bytes as SVG, reaching a parser the application configured Next.js to exclude.

The source allowlist still holds — the image has to come from somewhere you permitted — but within that constraint, a file that lies about being AVIF reaches an SVG parser you explicitly tried to keep out. Vercel is careful to say this does not itself demonstrate XSS or RCE; what it demonstrates is that a security control you set (dangerouslyAllowSVG: false) could be walked around, which increases your exposure to whatever SVG-parser bug comes next. It scores highest of the seven because it defeats an explicit, intentional defense.

The one non-cache advisory is still worth your attention because of what it defeats. CVE-2026-119346 (CVSS 6.0) concerns Edge route handlers that set cookies with NextResponse.cookies.set():

...can expose the serialized cookie in the internal x-middleware-set-cookie response header. Unlike Set-Cookie, this header can be read by same-origin JavaScript, exposing cookie values even when they are marked HttpOnly.

HttpOnly exists for exactly one reason: to make a cookie invisible to JavaScript, so that a cross-site-scripting bug cannot read your session token. This advisory routes the cookie's value into a different header that is script-readable, which quietly undoes the one guarantee HttpOnly is supposed to provide. It is not an independent way to run JavaScript — it needs an XSS foothold you already have — but it means that on an affected Edge route, HttpOnly stopped being the backstop you were relying on. Node.js route handlers and routes using cookies().set() were not affected in Vercel's reproduction, which narrows it, but if your auth cookies are set on Edge routes, this is the one to check first.

We recommend reading What Is Supply-Chain Security? to continue reading our selection of content. Your framework is the largest single dependency in a web app, and when it makes seven correctness decisions wrong at once, every app built on it inherits them.

What Is Supply-Chain Security? Why the integrity of what you build on matters as much as the code you write. SudoSecurity

What To Do

Upgrade. The fixed releases are 16.4.5 for the 16.x line and 15.5.29 for the 15.5 line; as of this writing npm's latest has already moved on to 16.4.6, so take the newest patch on your line rather than pinning to the exact security release:

npm install next@16.4.6   # 16.x line (16.4.5 is the security fix; 16.4.6 is newer)
npm install next@15.5.29  # 15.5 maintenance line

Then triage by what you actually run, because not every one of these is live in every app:

  • If you do not use Cache Components / use cache, the four cache-identity bugs do not apply to you. This is an opt-in feature. If you never enabled it, you were never exposed to those four. Confirm before you panic.
  • If you self-host with next start, the three self-hosted advisories are your priority. Check whether Partial Prefetching is enabled (it blunts the shell-poisoning bug), stop returning upstream Response objects unchanged, and if your auth cookies are set on Edge routes, audit that path for the HttpOnly leak.
  • If you deploy to a managed platform, you are still in the affected version ranges for the framework bugs — hosting does not exempt you from code that ships in your bundle. It only absorbs the three that depend on your own server infrastructure.

The affected ranges are wide: the cache bugs reach back across the entire 16.x series to 16.0.0 (one to 16.2.0, one to 16.3.0), and the three with a 15.x range cover 15.0.0 through 15.5.28. If you have not updated Next.js since before November, assume you are in range for several of these and upgrade rather than checking them one at a time.

What This Doesn't Cover

I have the mechanisms verbatim from Vercel's own security-release post, which is the primary source, and I confirmed the version facts directly against npm — 16.4.5 and 15.5.29 exist, 16.4.6 is now latest, and 15.5.28 and 16.4.4 are the last vulnerable builds on each line. I did not reproduce any of the seven. These are cache-semantics and response-framing bugs that need a full application, a specific feature configuration, and in several cases a particular proxy topology to trigger; a faithful reproduction is a project per advisory, not a shell script, and I will not hand-wave one. Where I describe a mechanism, it is Vercel's description, quoted, not my reading of the Next.js source — I did not read the fix commits.

The CVSS scores are as reported by secondary trackers citing the GitHub advisory records; I did not recompute all seven vectors myself. The one score/label discrepancy I flagged — High in prose, 6.3 in CVSS — is the vendor's own, not an error I'm introducing. The self-hosted-versus-not split is from Vercel's wording about which deployments the reproductions affected; edge cases in unusual configurations may differ.

Out of scope: the October 2026 Next.js RCE advisories, which are a separate release; the general argument about whether aggressive caching is worth its complexity; and any judgment about Cache Components as a feature. Four security bugs in a young caching primitive is what a first hard look usually finds, not a verdict on the design.

The Actual Point

Caching is where correctness goes to get complicated, and it's complicated for a reason no framework can abstract away: the cache key is a claim about identity, and identity is the hardest thing in any multi-tenant system to pin down. Six of these seven advisories are the same sentence written six ways — this thing and that thing are the same, so reuse the answer — said a little too confidently, a little too early, before the system had finished working out whose answer it was.

For the self-hoster specifically, there is a sharper lesson underneath. Three of these seven are yours to carry because you run the server, and that is the actual trade of self-hosting Next.js. You get control, portability, and freedom from a platform's pricing and lock-in, and in exchange you inherit the response-framing, the reverse proxy, the image backend, and the next start process as your attack surface rather than someone else's. That's a defensible trade — plenty of good reasons point to self-hosting — but it's a real one, and a release like this is the invoice arriving. The managed platform was quietly paying three of these bills for its customers. If you left, you took the bills with you.

Upgrade to the latest patch on your line, find out whether you actually use Cache Components, and if you self-host, treat the three next start advisories as the ones with your name on them. The cache will go back to being a speed-up the moment the identity function is correct — which, as of 16.4.5, it is.

The seven advisory mechanisms are quoted from Vercel's November 2026 security-release post. The version facts (16.4.5, 15.5.29, 16.4.6 as current latest) are verified directly against npm. No advisory was reproduced, and the Next.js source at the fix commits was not read; those limitations are stated above.

$ tail -f /forums

Discussion

Comments live on the community forums — sign in there to reply.