← Blog
·9 min read

CVE-2025-29927: One HTTP Header That Unlocks Every Protected Route in Next.js

A single HTTP header bypassed every middleware-based authentication check in Next.js. No exploit code needed. No login required. Just one header and the dashboard was open.

Rod Alexanderson

Founder

Most developers think about authentication in terms of what the attacker has to break. A login form. A JWT. A session cookie. The mental model is: the attacker tries to get past the lock.

CVE-2025-29927 was a different kind of problem. There was no lock to pick. The attacker just told Next.js the request was internal — and Next.js believed them.

One HTTP header. No authentication needed. Every route your middleware protected was open.


What CVE-2025-29927 is

Next.js middleware sits between every incoming request and your application. You use it to check sessions, validate tokens, redirect unauthenticated users, enforce role-based access. It's the standard pattern for protecting routes in modern Next.js apps — and the one most AI assistants generate when you ask for authentication scaffolding.

The vulnerability, CVE-2025-29927, affected Next.js versions 11.1.4 through 15.2.2. That's roughly four years of releases. Any app running those versions with middleware-based auth was exposed.

The CVSS score is 9.1 — Critical.

The fix shipped in 14.2.25 (for 14.x users) and 15.2.3 (for 15.x users).

What makes this one significant isn't just the score. It's how simple the exploit is. You don't need to reverse-engineer a cryptographic flaw. You don't need a payload. You add one header to your HTTP request, and middleware stops running.


How the bypass works

Next.js has an internal mechanism for handling subrequests — requests that the framework makes to itself as part of server-side rendering. When a subrequest comes in, Next.js skips middleware to avoid infinite loops. That's by design.

The problem is that Next.js determined whether a request was an internal subrequest by checking a specific HTTP header: x-middleware-subrequest. And it trusted that header without validating where the request actually came from.

An external attacker could add that header to any request. Next.js saw it, assumed the request was internal, and skipped middleware entirely.

The header value that triggers the bypass depends on your project layout:

Pages Router (Next.js 11.1.4–12.1.x):

x-middleware-subrequest: pages/_middleware

App Router without /src directory (Next.js 12.2.x–13.x):

x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware

App Router with /src directory (Next.js 14.x–15.2.2):

x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middleware

That's it. No special tooling. No elevated access. Just curl.


What an attacker actually does

Here's what a request to a protected dashboard looks like without the exploit. The middleware runs, checks the session, and redirects:

curl -v https://yourapp.com/dashboard
# Response: 307 Temporary Redirect → /login

Now with the bypass:

curl -v \
  -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" \
  https://yourapp.com/dashboard
# Response: 200 OK — full dashboard content

The middleware never ran. No session check happened. The server returned the page as if the user was authenticated.

This works against admin panels, user dashboards, internal tools, billing pages — anything your middleware was protecting. If the route was behind a middleware.ts redirect and nothing else, it was open.


The exact middleware pattern that's vulnerable

Here's a typical middleware.ts that protects all routes under /dashboard:

// middleware.ts — VULNERABLE on Next.js < 14.2.25 / 15.2.3
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 
export function middleware(request: NextRequest) {
  const token = request.cookies.get('session-token')
 
  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url))
  }
 
  return NextResponse.next()
}
 
export const config = {
  matcher: ['/dashboard/:path*', '/admin/:path*'],
}

This code is correct. The logic works as intended. But on vulnerable Next.js versions, the attacker never triggers this function. The framework skips it before this code runs.

The only patterns that survived the bypass were those with a secondary auth check inside the route handler or page itself:

// app/dashboard/page.tsx — secondary check that CVE-2025-29927 cannot bypass
import { getServerSession } from 'next-auth'
import { redirect } from 'next/navigation'
 
export default async function DashboardPage() {
  const session = await getServerSession()
 
  // This runs regardless of middleware
  if (!session) {
    redirect('/login')
  }
 
  return <Dashboard />
}

If your only line of defense was the middleware redirect, CVE-2025-29927 bypassed it completely.


Why this pattern is everywhere

The middleware-only auth pattern is exactly what AI assistants generate. Ask Cursor, Copilot, or any AI scaffold tool for "Next.js authentication" and you get middleware.ts with a session check and a redirect. It's the recommended pattern in the Next.js docs. It's clean. It works.

The problem is that it became the only layer for a lot of apps — especially ones built fast, by a single developer, where "I'll add a server-side check later" never happened.

The typical vibe-coded SaaS has a middleware.ts protecting /dashboard, /settings, and /admin. Behind that middleware, the page components fetch data and render it without checking the session again. Why would they? The middleware handles it.

Under CVE-2025-29927, that assumption was wrong. And unlike a logic bug you can test manually, there's nothing in the UI that shows you whether middleware ran or not. Your app looks fine. The exploit is invisible in normal usage.

DataHogo's scanner checks for single-layer middleware authentication patterns — where middleware is the only enforcement point with no secondary validation in the route itself. Run a free scan.


How to check if your app is affected

First, check your Next.js version:

npm list next
Version line Vulnerable range Safe version
Next.js 11.x 11.1.4 – 11.x No patch — upgrade to 14.x+
Next.js 12.x 12.x all No patch — upgrade to 14.x+
Next.js 13.x 13.x all No patch — upgrade to 14.x+
Next.js 14.x 14.0 – 14.2.24 14.2.25+
Next.js 15.x 15.0 – 15.2.2 15.2.3+

If you're on 14.x or 15.x, update:

npm install next@latest

Second, search your logs for the bypass header. On most hosting providers you can grep request logs:

grep "x-middleware-subrequest" your-access.log

On Vercel, use the log filters in the dashboard. Any hit on that header from an external IP during the vulnerable window is worth investigating — check what route was requested and what the response code was.

Third, audit your route protection. Find every route that only has a middleware redirect as its auth layer:

# Find all page files that don't contain a session check
grep -rL "getServerSession\|auth()\|getSession\|verifyToken" app/**/page.tsx

Cross-reference that list with your middleware matcher config. Any route that appears in both is worth adding a server-side check to, regardless of the CVE.


Three things to do today

1. Update Next.js immediately.

If you're on 14.x, go to 14.2.25+. If you're on 15.x, go to 15.2.3+. If you're on anything older — 11, 12, 13 — those versions have no patch and you should migrate to a supported release. This is not optional.

2. Add server-side auth checks to your most sensitive routes.

Middleware is a good first layer. It should not be the only layer. For any route where exposure would be damaging — admin panels, billing, user data — add a session check directly in the page or route handler. It takes three lines of code and it makes your auth resilient against this entire class of bypass.

3. Review your logs for the window your app ran on a vulnerable version.

If your app was publicly accessible on a vulnerable Next.js version, check your logs for the x-middleware-subrequest header. If someone exploited this against you, the evidence is there. Act on it: determine what was accessible, assess what data those routes could return, and notify affected users if necessary.


TL;DR

  • CVE-2025-29927 is a critical authentication bypass in Next.js, CVSS 9.1, affecting versions 11.1.4 through 15.2.2.
  • An attacker adds a single HTTP header — x-middleware-subrequest — to any request, and Next.js skips middleware entirely.
  • Any route protected only by a middleware redirect was fully accessible to unauthenticated requests.
  • The fix is Next.js 14.2.25+ or 15.2.3+. Older versions (11, 12, 13) have no patch — migrate.
  • Apps with a secondary auth check inside the route handler or page component were not bypassed by this vulnerability.
  • The middleware-only auth pattern is the default scaffold from every AI assistant. Check your routes.

FAQ

Does CVE-2025-29927 affect Next.js Pages Router or only App Router?

Both. The specific header value changes depending on your project structure, but the bypass works across routing systems. Pages Router uses x-middleware-subrequest: pages/_middleware. App Router without /src uses the middleware segment repeated five times. App Router with /src uses src/middleware repeated five times.

If my auth checks happen inside the page component and not just in middleware, am I vulnerable?

Not to this specific bypass. CVE-2025-29927 only skips middleware execution. If you have a session verification or token check inside the page or API route itself, that check still runs. The vulnerability specifically targets setups where middleware is the only layer enforcing access control.

Is upgrading to 14.2.25 or 15.2.3 enough, or do I need to do anything else?

Upgrading patches the vulnerability going forward. But if your app ran a vulnerable version on a public URL, an attacker may have already accessed protected routes during that window. Review your access logs for requests containing the x-middleware-subrequest header. If you find hits, audit what those routes exposed and respond accordingly.

My auth is handled by a third-party provider like Clerk or NextAuth. Am I affected?

Possibly. Many auth providers for Next.js implement their session validation inside middleware. If the middleware is the only thing checking the session before letting a request through, CVE-2025-29927 bypasses it. Check whether your provider has released a specific advisory or updated their middleware integration in response to this CVE.

CVENext.jsmiddlewareauthenticationauth bypassApp Routervulnerabilities