Shattered glass scattered across carpet, with the words 'CVE Burden' overlaid, representing the accumulated weight of security vulnerabilities

Why Next.js Has 11x More CVEs Than Express

A team running Express typically spends less time chasing npm audit alerts than a team running Next.js: fewer dependency warnings, fewer version bumps forced by a security advisory, less time reading changelogs to figure out whether a patch actually applies to how the app is configured. That’s a real, if modest, quality-of-life difference.

The bigger question is how much of that difference is coincidence, and how much of it is structural, a direct consequence of how much infrastructure a framework owns versus how much it leaves alone.

TL;DR

  • As of July 18, 2026, Next.js has 55 known vulnerabilities catalogued in the OSV database. Express has 5. Same source, same date, directly comparable: roughly 11 times more.
  • The gap isn’t just volume. 23 of Next.js’s 55 vulnerabilities, 42%, are rated High or Critical severity. None of Express’s 5 are rated above Moderate.
  • Two of Next.js’s critical vulnerabilities are as severe as web application security gets: an unauthenticated remote code execution with a maximum CVSS score of 10.0, and a middleware authorization bypass at 9.1, both disclosed in the last twelve months.
  • Scope alone doesn’t explain the gap. Nuxt, a comparably-scoped meta-framework with its own bundler and SSR layer, has 6 known vulnerabilities, close to Express’s 5, despite being similarly popular. A same-category comparison rules out framework size alone as the explanation.
  • Several Next.js patches required a second, follow-up CVE after the first fix turned out to be incomplete, itself a signal about how much surface area the framework has to get right.
  • This isn’t a claim that Next.js is broadly insecure. It’s the same architectural argument already made about memory in this series, applied to security: a framework that owns more subsystems has more places for something to go wrong, whether that’s a cache growing unbounded or an authorization check that can be skipped.

The numbers, same source, same date

Per a security audit tool checking both packages against Google’s OSV database on 2026-07-18, Next.js has 55 known vulnerabilities and Express has 5. Both counts come from the same methodology on the same day, which makes them about as directly comparable as vulnerability data gets.

Severity is where the comparison sharpens. Next.js’s 55 break down as 2 Critical, 21 High, 27 Moderate, and 5 Low, meaning 23 of 55 (42%) sit at High or Critical. Express’s 5 top out at Moderate (a CVSS score of 5.0), with the rest rated Low. Volume alone would already be a meaningful difference. The severity distribution makes it a different kind of difference.

A fair objection to raise here directly: Next.js is a full meta-framework with a bundler, an image pipeline, and a rendering engine, while Express is a thin routing library, so a higher count might just reflect more code to have bugs in, not anything specific to Next.js. A same-category comparison tests that directly.

PackageKnown vulnerabilitiesScope
Express5Routing and middleware library
Nuxt6Full meta-framework: bundler, SSR, hydration (Vue)
Next.js55Full meta-framework: bundler, SSR, hydration, RSC

Nuxt is a comparably-scoped meta-framework, its own bundler, server-side rendering, and hydration and serialization layer, built on Vue instead of React, and it isn’t under-scrutinized either: Snyk rates it a “key ecosystem project” on the strength of 1.5 million weekly downloads. Its count lands close to Express’s, not anywhere near Next.js’s. That’s evidence the gap isn’t simply explained by meta-frameworks accumulating more vulnerabilities by nature.

The two most severe cases

CVE-2025-55182, publicly nicknamed “React2Shell,” is an unauthenticated remote code execution vulnerability in how React Server Components deserialize data sent from client to server. The official GitHub Security Advisory, published directly by React’s own repository, lists a CVSS score of 10.0, the maximum possible, and an EPSS score of 99.562%, meaning the modeled probability of real-world exploitation within 30 days was assessed at essentially certain. Wiz Research documented that a standard application built with create-next-app and deployed with default settings was vulnerable with no code changes required, and that exploitation was subsequently observed in the wild by multiple independent security teams, including post-exploitation activity involving cloud credential theft and cryptocurrency mining.

CVE-2025-29927 is a middleware authorization bypass, CVSS 9.1, that let an attacker skip authentication and access-control checks entirely by spoofing a single internal HTTP header. The official GitHub Security Advisory lists an EPSS score of 92.118% for this one, also close to certain. That same advisory states plainly that “Next.js deployments hosted on Vercel are automatically protected against this vulnerability,” which leaves self-hosted deployments as the ones actually carrying the exposure, the same self-hosted-versus-managed-infrastructure divide already covered in this series’ memory leak case study.

Thirteen advisories in one release

In May 2026, Vercel shipped a single coordinated security release patching 13 advisories at once: 5 covering middleware and proxy bypass, 3 denial of service, 1 server-side request forgery, 2 cache poisoning, and 2 cross-site scripting. That breadth is itself informative. Those aren’t five variations on one bug, they’re five structurally distinct categories of vulnerability, spanning the routing layer, the rendering layer, the caching layer, and script handling, patched together because they’d all accumulated across the same release cycle.

Shipping thirteen advisories together, each with a clear CVSS and EPSS score attached, is what a mature, transparent disclosure process looks like, not a sign of carelessness. Vercel’s security team has enough of a track record here that other frameworks lean on it directly: the Svelte team’s own January 2026 disclosure of five separate CVEs explicitly credits Vercel’s security team for helping them navigate the process. The volume of advisories reflects real surface area, not a slow or evasive response to it.

A related pattern shows up more than once in the fuller vulnerability list: fixes that needed a second, follow-up CVE after the first patch turned out to be incomplete. A Server Components denial-of-service issue and a segment-prefetch middleware bypass both required a documented “incomplete fix follow-up” advisory. Getting a fix right the first time is harder when the surface being patched is large and interconnected.

What Express actually has

Express’s 5 known vulnerabilities are unremarkable by comparison: a resource injection issue, a missing charset header, an open redirect in malformed URLs, a second open redirect, and reflected XSS via response.redirect(). Nothing rated above Moderate, nothing involving authentication bypass or remote code execution, several dating back a decade. That’s not a claim that Express is exceptionally well-engineered, it’s a routing and middleware library with a much smaller surface to begin with. A bundler, an image optimization pipeline, a server-side rendering engine, and a component serialization protocol simply aren’t things Express has to get right, because it was never asked to own them.

Why this happens, architecturally

This is the same argument already made about memory in this series, applied to a different failure mode. A framework that owns more subsystems, a bundler, an image pipeline, a caching layer, an RSC serialization format, a middleware execution model, has more places for something to break, whether that something is a cache growing without bound or an authorization check that a spoofed header can skip. Express doesn’t have a middleware-bypass CVE class the way Next.js does, not because Express’s middleware is more carefully written, but because Express’s middleware model is a thin, well-understood primitive with a much smaller space of things that can go wrong in it.

The categories track the architecture rather than any one team’s coding standards. SvelteKit’s January 2026 disclosures, built by an entirely separate team on a different rendering model, covered memory and CPU exhaustion in its data-serialization layer, server-side request forgery, and cross-site scripting through unsanitized data embedded in server-rendered markup, the same categories of failure that show up in Next.js’s own advisory history. Different codebases, same architectural shape, same kinds of bugs.

Frequently asked questions

Isn’t this just because Next.js is a bigger framework?

That’s a fair question, and Nuxt is the test case. Nuxt is a comparably-scoped meta-framework, its own bundler, server-side rendering, and hydration layer, and it isn’t obscure either, at 1.5 million weekly downloads. It has 6 known vulnerabilities, close to Express’s 5, not anywhere near Next.js’s 55. Scope alone doesn’t explain the gap.

Does this mean Next.js is insecure?

Not as a blanket claim. It means Next.js owns substantially more infrastructure, a bundler, an image pipeline, an RSC serialization layer, a middleware execution model, and each of those is a place a vulnerability can live that a thinner framework simply doesn’t have. The tradeoff is real in both directions: those subsystems also provide real capability a minimal stack doesn’t have out of the box.

Are these vulnerabilities exploitable in typical self-hosted setups?

Several specifically are. CVE-2025-29927’s own advisory notes Vercel-hosted deployments are automatically protected, which by implication means self-hosted deployments running affected versions were not. CVE-2025-55182 was exploitable in a default create-next-app configuration with no custom code involved.

Should this be the deciding factor in choosing a framework?

On its own, no. Vulnerability count and severity are one input among several, alongside team familiarity, feature requirements, and how quickly an organization can actually apply patches. It’s a meaningful data point, not a complete decision by itself.

Related reading

This connects directly to the memory leak case study earlier in this series, which makes the same architectural argument, more owned infrastructure, more surface for something to go wrong, about memory rather than security, and specifically about the same self-hosted-versus-Vercel divide that shows up again here.

RSS Feed Newsletter
Contact us

Latest Blog Posts