HomeGuidesNext.js middleware auth bypass CVE-2025-29927

Guide

Next.js middleware auth bypass CVE-2025-29927

CVE-2025-29927 let one header skip Next.js middleware auth checks. Affected versions, the patched releases, who is safe, and how to fix your app.

7 min read

Independent notes from VibeLocked. Not a pentest, and not affiliated with the tools named below.

If your Next.js app checks login in middleware.ts and you host it yourself, an old bug could let anyone skip that check. It is tracked as CVE-2025-29927. Many AI generated Next.js projects from Cursor, v0, Bolt, or Lovable put auth in middleware, so it is worth five minutes to confirm you are on a fixed version.

Checked against the Next.js postmortem, the GitHub advisory, NVD, and the Next.js docs linked below on October 14, 2026.

The short answer

Your Next.js line Affected versions Fixed in
15.x 15.0.0 to 15.2.2 15.2.3
14.x 14.0.0 to 14.2.24 14.2.25
13.x 13.0.0 to 13.5.8 13.5.9
12.x 12.0.0 to 12.3.4 12.3.5
11.x 11.1.4 and later No patch, upgrade or block the header
16.x Not in the affected range Already includes the fix

These ranges come from the GitHub advisory GHSA-f82v-jwr5-mffw and the NVD entry for CVE-2025-29927. The advisory rates it Critical, 9.1 out of 10.

Where your app runs Affected?
Vercel No, protected automatically
Netlify No, never affected
Cloudflare Workers No, never affected
Static export (output: 'export') No, there is no middleware
Self-hosted with next start or output: 'standalone' Yes, if your version is in the range above

What happened, in plain words

Middleware (Next.js 16 renamed it Proxy) runs before your pages and API routes. A common pattern is to read the session cookie there and redirect anyone who is not signed in.

Next.js used an internal header called x-middleware-subrequest to know that middleware had already run, so it would not loop forever. The problem was that Next.js also trusted that header when it came from outside. A request that included it could make Next.js skip your middleware entirely. If your only auth check lived in middleware, the protected page or route was served anyway.

The official postmortem, published by the Next.js team, explains the fix: Next.js now validates that header and filters it out if the validation fails. Patches shipped on March 17 and 18, 2025 for 14.x and 15.x, with backports to 13.5.9 and 12.3.5 a few days later.

Are you affected? Three questions

  1. Do you host it yourself? If your app is on Vercel, Netlify, or Cloudflare Workers, or you use a static export, you were not exposed through this bug. The postmortem confirmed that self-hosted apps using next start or output: 'standalone' were affected. That includes a VPS, a Docker container, or any host that runs your app as a plain Node server.
  2. Are you on an affected version? See the next section.
  3. Does your middleware do auth? If your middleware.ts (or proxy.ts) redirects signed out users, checks roles, or guards /admin or /dashboard, that check could be skipped. If you have no middleware file, this bug had nothing to skip, but you should still upgrade.

How to check your Next.js version

Open package.json and find the next line under dependencies. A value like "^14.2.3" is a range, not the exact version you have installed. To see the real installed version, run this in your project folder:

npm ls next

The output shows something like next@14.2.24. Compare that number with the table above. If you use pnpm or yarn, pnpm list next or yarn why next gives the same answer. Also check the version your host actually builds with. If your lockfile is committed, that is usually the same number. For an outside view, the free Live App Scanner fingerprints the Next.js build a deployed app exposes and flags this CVE when it can see an affected version, but npm ls next is the reliable answer.

The fix: upgrade Next.js

Move to at least the fixed release for your major version, for example:

npm install next@14.2.25

Use 15.2.3, 13.5.9, or 12.3.5 instead if you are on those lines. Going to the newest release of your line is even better, because later releases fixed other issues too. The Next.js support policy lists which major versions still get security patches. Commit the updated package.json and lockfile, redeploy, and run npm ls next again to confirm.

If your AI tool generated the project months ago, ask it to do the upgrade and then run your app locally to confirm sign in, sign out, and protected pages still behave. Read the diff for anything else it installs on the way: a package name a model invents can be registered by an attacker (AI hallucinated packages).

If you cannot upgrade yet: block the header

The advisory says that if patching is not possible, stop outside requests that contain the x-middleware-subrequest header from reaching your Next.js app. You do that in whatever sits in front of it:

  • nginx as a reverse proxy. In the location block that passes traffic to Next.js, add proxy_set_header x-middleware-subrequest "";. nginx's proxy module docs say a header set to an empty string is not passed to the app.
  • A CDN or firewall in front of your server. Add a rule that blocks or strips requests carrying that header.

This is a stopgap for Next.js 11 or a frozen legacy app. It is not a reason to skip the upgrade.

The bigger lesson: middleware is not your auth boundary

The postmortem says plainly that the Next.js team does not recommend middleware as the only way to protect routes. The current Next.js authentication guide calls Proxy an optional place for "optimistic checks" that only read the session cookie, and says it "should not be your only line of defense in protecting your data." It recommends doing most checks "as close as possible to your data source."

So keep your middleware redirect for a smooth user experience, and also check auth where the data is:

  • Route Handlers. The same guide says to treat them like public API endpoints and verify the user inside each one.
  • Server Actions. Anyone can call them with a direct POST. See Next.js Server Actions security.
  • Your data access code. Put a verifySession() style helper in one module and call it before every read or write of private data.
  • Admin pages. A client component that redirects non-admins is UI only. Check the role in the Server Component, the action, and the handler. The client-side auth guide has a requireAdmin() helper for Supabase and Clerk.
// app/api/orders/route.ts
import { verifySession } from '@/app/lib/dal';

export async function GET() {
  const session = await verifySession();
  if (!session) {
    return new Response(null, { status: 401 });
  }
  // Only fetch orders that belong to session.userId
}

verifySession is a placeholder for your own auth helper, like the one in the Next.js guide. Filtering by the session user is the IDOR fix; fix IDOR in Next.js and Supabase has the full pattern and a two-account test. On Supabase, RLS is the backstop for a check you miss, and testing RLS policies in CI keeps it from quietly regressing. The Proxy docs add another reason: a matcher change can silently stop Proxy from running on a route, so they say to verify auth inside each Server Function rather than relying on Proxy alone.

The common vibe coded app vulnerabilities guide covers this and other missing auth patterns AI tools tend to produce.

Ask your AI tool to audit it

Open your project in Cursor or your AI tool and ask: "List every page, Route Handler, and Server Action that reads or changes private data. For each one, show where it checks the session. Flag any that are only protected by middleware.ts or proxy.ts." The security review prompt gives a fuller version.

Checklist

  • npm ls next shows 15.2.3, 14.2.25, 13.5.9, 12.3.5, or newer in your line
  • Or your app runs on Vercel, Netlify, Cloudflare Workers, or is a static export
  • If stuck on an old version, the proxy in front strips x-middleware-subrequest
  • Every Route Handler with private data checks the session itself
  • Every Server Action checks the session and ownership itself
  • Middleware or Proxy is only used for redirects, not as the only lock

Sources

Questions

Is my Next.js app on Vercel affected by CVE-2025-29927?

No. The GitHub advisory says Next.js deployments hosted on Vercel are automatically protected. The Next.js postmortem also says Netlify and Cloudflare Workers were never affected, and static exports are not affected because they have no middleware. Self-hosted apps using next start or output: 'standalone' were affected.

Which Next.js version fixes CVE-2025-29927?

15.2.3 for Next.js 15, 14.2.25 for Next.js 14, 13.5.9 for Next.js 13, and 12.3.5 for Next.js 12. There is no patch for Next.js 11, so upgrade or block the x-middleware-subrequest header in front of your app. Next.js 16 is not in the affected range.

If I block the x-middleware-subrequest header, do I still need to upgrade?

Yes. The advisory lists blocking the header as a workaround for when patching is not possible. Upgrading is the real fix, and you should also move real auth checks into Route Handlers, Server Actions, and your data access code so one skipped middleware check cannot expose data.