groundy
security

Vercel's Next.js Middleware Bypass Postmortem: What the Fix Reveals About Edge Runtime Auth

Two separate Next.js production failures — a header bypass CVE and an Edge Runtime mismatch — show middleware is not a reliable sole auth layer for self-hosted deployments.

6 min · · · 5 sources ↓

Next.js middleware was never designed to be a security boundary, but a year of CVEs and production incidents shows the ecosystem built one anyway. CVE-2025-29927[^1] let attackers skip middleware entirely via a single HTTP header. A separate incident in March 2026 exposed 23 admin routes for 11 days through a runtime mismatch that neither CI nor local development caught. Both failures trace back to the same assumption: that middleware is a reliable chokepoint for authorization.

How CVE-2025-29927 worked

On March 21, 2025, ProjectDiscovery disclosed a critical vulnerability (CWE-863: Incorrect Authorization[^2]) affecting Next.js versions 11.1.4 through 15.2.2.[^1] The attack was straightforward: sending an x-middleware-subrequest header containing the middleware filename caused Next.js to treat the request as an internal subrequest, skipping the middleware’s authorization logic and passing the request through to the route handler.

The header payload was not obscure. ProjectDiscovery provided a Nuclei detection template that automatically extracted endpoints from a target and tested both middleware:middleware:... and src/middleware:src/middleware:... variants.[^1] Anyone running a vulnerable version with middleware-based auth was exploitable with a single curl command.

The postmortem timeline

Vercel’s postmortem reveals a 22-day gap between initial disclosure on February 27, 2025 and the public CVE on March 21.[^3] The delay was partly organizational: reports came in fragmented across GitHub private reporting and security@vercel.com in separate threads, slowing triage.

Vercel committed to documenting internal headers and building an official deployment adapters API with Netlify and Cloudflare, according to the postmortem.[^3] That work appears ongoing.

Who was actually vulnerable

The most revealing detail in the postmortem is what Vercel calls being “incidentally invulnerable.” Vercel-hosted applications were unaffected because Vercel’s routing layer runs in a separate global system decoupled from middleware.[^3] Netlify and Cloudflare Workers deployments were also safe for the same architectural reason.

Self-hosted Next.js deployments using next start or output: 'standalone' were the ones exposed.[^3] The platform that popularized middleware-based auth patterns was protected by infrastructure that bypassed the pattern entirely. Everyone self-hosting was on their own.

A different bug, the same assumption

Darshan Turakhia published a postmortem on March 24, 2026 describing a distinct failure that exposed 23 admin API routes for 11 days in a B2B SaaS application.[^4] This is not CVE-2025-29927.[^1] The header bypass was already patched. Instead, the root cause was a runtime mismatch that silently disabled authorization.

The mechanism: Next.js middleware runs on the Edge Runtime in Vercel production but on Node.js in next dev. The application used the jsonwebtoken library for JWT verification in middleware. jsonwebtoken depends on Node’s crypto module, which does not exist in the Edge Runtime. When JWT verification failed on Edge, the catch block swallowed the error and returned a 200 response for all requests.[^4] Every admin route was open, and nothing in CI or local testing caught it because both run against Node.

The dev-prod runtime gap

This is the structural problem neither CVE fix addresses. Vercel production executes middleware in the Edge Runtime, a V8-based environment that supports Web APIs but not Node.js APIs. Local development runs middleware in Node.js. A library that works in development and CI can fail silently in production, and the only way to catch it is to test against an Edge-compatible environment.

Standard CI pipelines run next build and next start, both of which use Node. Preview deploys on Vercel run on Edge. The gap between these two environments is invisible until a Node-only library is called in production, at which point it either throws or, worse, fails into a permissive default.

What the fixes actually require

The Turakhia incident makes the structural fix clear. Any library used in middleware must be compatible with the Edge Runtime. The jsonwebtoken package depends on Node’s crypto module, which does not exist in Edge, and that incompatibility was the direct cause of the auth bypass.[^4] Middleware that calls Node-only APIs will fail on Edge, and if that failure is caught silently, authorization is bypassed by default.

Integration tests must also run against the actual Edge Runtime, not just next start in CI. A test suite that passes on Node proves nothing about production behavior on Edge. Preview deploys on Vercel run on Edge; targeting those in CI closes the verification gap.

Middleware is a request hook, not a security boundary

Vercel’s postmortem and the Turakhia incident together expose a pattern the ecosystem walked into. Middleware in Next.js is a request-phase hook. It runs before route handlers and can short-circuit requests, which makes it tempting to use as the sole authorization layer. But it has two properties that disqualify it from that role: the runtime it executes in differs between environments, and the framework reserves the right to change how internal subrequests traverse it.

The fix is not to remove middleware auth. It is to stop treating it as the only auth layer. Authorization checks in route handlers are not redundant when the middleware can be bypassed by a header, a runtime failure, or a framework-level routing change. Two production incidents in twelve months, exploiting different failure modes in the same assumption, make the case for defense in depth.

Vercel disclosed a separate security breach on April 19, 2026, originating from a compromised third-party AI tool (Context.ai) that led to unauthorized access to employee Google Workspace accounts and some non-sensitive environment variables.[^5] That incident is unrelated to the middleware bypass but adds context to Vercel’s security posture during the same period.

Frequently Asked Questions

What build-time rule forces Edge Runtime incompatibilities to surface before deploy?

Adding export const runtime = 'edge' to route handlers makes Next.js validate Edge compatibility at build time — any imported module touching Node APIs causes a hard build failure rather than a silent runtime bypass. The consistent-return ESLint rule is a complementary guard that flags catch blocks falling through to implicit returns instead of explicit 401/403 responses.

Why were Netlify and Cloudflare Workers deployments safe from CVE-2025-29927?

These platforms route requests through their own gateway layers before the request reaches the Next.js instance, and neither forwards the x-middleware-subrequest header to the application. Self-hosted next start has no such gateway, so the internal header reaches the Next.js router unfiltered.

Do App Router server components have the same Edge Runtime vulnerability as middleware?

No. Server components default to Node.js runtime even on Vercel, so Node-only libraries like jsonwebtoken work there without issue. Middleware is the only layer Vercel forces onto Edge by default, which is why the runtime mismatch surfaces exclusively in that boundary.

What other common Node libraries break on Edge Runtime the same way jsonwebtoken does?

Any package depending on crypto, fs, net, or child_process will throw or silently fail. Notable examples include bcrypt (native bindings), passport strategies that rely on Node streams, and any middleware ported from Express. Edge-compatible replacements include jose for JWT operations, bcryptjs for hashing, and the built-in fetch global.

  1. CVE-2025-29927: Next.js Middleware Authorization Bypass - Technical Analysis analysis accessed 2026-05-23
  2. NVD: CVE-2025-29927 primary accessed 2026-05-23
  3. Postmortem on Next.js Middleware bypass vendor accessed 2026-05-23
  4. Our Next.js Middleware Silently Bypassed Auth on 23 Admin Routes for 11 Days community accessed 2026-05-23
  5. Vercel primary accessed 2026-05-23