CVE-2025-29927: the Next.js middleware bypass, who is affected and how to fix it

CVE-2025-29927 is a critical Next.js flaw (CVSS 9.1) that let anyone skip middleware by sending one internal header, x-middleware-subrequest. If your login check lived only in middleware.ts, protected pages opened with no session. It hit self-hosted Next.js 11.1.4 to 15.2.2; Vercel and Netlify were not exposed. Fixed in 15.2.3, 14.2.25, 13.5.9 and 12.3.5; in November 2026, upgrade to 16.4.5 or 15.5.29.

The team behind Keybrum's attacksUpdated 12 min read
CVE-2025-29927critical · CVSS 9.1
Component
Next.js middleware (next)
Affected
Next.js 11.1.4 to 15.2.2: 11.1.4 and 12.x before 12.3.5, 13.x before 13.5.9, 14.x before 14.2.25, 15.x before 15.2.3, when self-hosted with middleware
Fixed in
15.2.3, 14.2.25, 13.5.9, 12.3.5 (follow-up fix: 15.2.4, 14.2.26, 13.5.10, 12.3.6). Current patches: 16.4.5 or 15.5.29
Published
March 21, 2025
Keybrum tests your live app for this one, and proves it if it works.

In short

  • A request carrying the internal x-middleware-subrequest header made Next.js skip middleware. A page whose only login check sat in middleware.ts opened for anyone, with no account.
  • Affected: Next.js 11.1.4 to 12.3.4, 13.x before 13.5.9, 14.x before 14.2.25 and 15.x before 15.2.3, on a server you run with next start or the standalone output. Vercel, Netlify, Cloudflare Workers and static exports were not exposed.
  • 15.2.3, 14.2.25, 13.5.9 and 12.3.5 are a floor, not a target. The middleware bypasses disclosed in 2026 are fixed only on 15.5 and 16, so upgrade to 16.4.5 or 15.5.29.
  • If you cannot upgrade today, strip the header at your reverse proxy or firewall. Cloudflare's managed rule for this CVE is opt-in, so sitting behind Cloudflare does not cover you by default.
  • The lasting fix is a session check in each page, route handler and Server Action, not only in middleware (called Proxy since Next.js 16).
On this page

What CVE-2025-29927 is, in plain words

Next.js middleware is a file, middleware.ts (renamed proxy.ts in Next.js 16), that runs on the server before a page is rendered. Many apps put their login check there: no session cookie, redirect to /login. The Next.js authentication guide shows exactly that pattern, as a quick first filter.

To stop middleware from calling itself in an endless loop, Next.js marked its own internal requests with a header, x-middleware-subrequest. The flaw: Next.js also trusted that header when it came from the internet. A request carrying the right value made Next.js skip middleware and render the page as if the check had passed. No account, no special tool: one HTTP header. Allam Rachid and Allam Yasser reported it on February 27, 2025, and the advisory went public on March 21, 2025.

What a stranger can do with it

If your middleware...Skipping it gives a stranger...
Redirects signed-out visitors to /loginThe protected page itself: dashboard, settings, admin screens, rendered with whatever the page loads on the server
Lets only admins into /adminThe admin page, unless the page checks the role again
Sets security headers such as Content-Security-PolicyThe page without them, which removes a defense against cross-site scripting
Rewrites paths, for example by languageAn error page that a cache in front of your app can store and serve to every visitor
The last two cases come from the researchers' write-up. The advisory itself covers the authorization bypass.

The limit matters as much as the risk. The bypass skips middleware and nothing else. If the page, the route handler or your data layer checks the session again, the stranger hits that second check, and database rules such as Supabase row level security still apply. It does not run code on your server either: it is an authorization bypass, not remote code execution like React2Shell.

Severity and exploitation status

The CVSS 3.1 base score is 9.1, critical, with the vector AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N: reachable over the network, low complexity, no privileges, no user interaction, high impact on confidentiality and integrity. The score comes from GitHub, the CVE numbering authority (CNA) that published the record. NVD has analyzed the CVE and shows that same score without publishing one of its own. The weakness is improper authorization: CWE-285 for the CNA, CWE-863 for NVD.

Who is affected

Three conditions together: a vulnerable version, a server that runs Next.js itself, and middleware that does the access control.

SetupAffected by CVE-2025-29927?
Next.js 11.1.4 to 12.3.4Yes, fixed in 12.3.5. The 11.x line got no patch of its own
Next.js 13.0.0 to 13.5.8Yes, fixed in 13.5.9
Next.js 14.0.0 to 14.2.24Yes, fixed in 14.2.25
Next.js 15.0.0 to 15.2.2Yes, fixed in 15.2.3
Next.js 15.2.3 and later, and every 16.xNo, but later middleware bypasses may apply, see below
Self-hosted: next start, the standalone output in Docker, a VPSYes, on a vulnerable version
Hosted on VercelNo: Vercel's routing runs in a separate system, which made it, in Vercel's words, incidentally invulnerable
Netlify, Cloudflare WorkersNo, per Vercel's postmortem: their routing is decoupled too
Static export (output: 'export')No: middleware does not run without a server
React without Next.js, such as a Vite single-page appNo: there is no Next.js middleware
Sources: the GitHub advisory, the CVE record and Vercel's postmortem. The postmortem does not cover other hosting setups: if your host runs next start for you, treat it as self-hosted.

One detail differs between sources. The CVE record and NVD start the range at 11.1.4, the last 11.x release; GitHub's npm advisory starts at 12.0.0, the release that introduced middleware, and sends 11.x users to the workaround. Either way, an app on 11.1.4 or 12.x needs 12.3.5 or later.

Apps built with AI tools

v0 generates Next.js apps and publishes them on Vercel, which was not exposed; the same code run with next start on your own server is, on a vulnerable version. A project created with create-next-app today starts on Next.js 16, so this CVE mostly concerns older projects and templates pinned to old versions. The v0 security guide covers the rest of a generated Next.js app.

Behind Cloudflare is not the same as on Cloudflare

If your server runs next start and Cloudflare only sits in front of it, requests still reach your vulnerable server. Cloudflare's managed WAF rule for this CVE is opt-in: you turn it on yourself, on the Pro plan and above. Cloudflare switched it off by default on March 22, 2025, after it made requests fail on sites that use auth middleware with third-party auth vendors. On the Free plan, Cloudflare suggests a custom rule, shown below. Akamai's rule also defaults to alert, not block.

How to check your Next.js version

Check the version that is installed, not the range in package.json: "next": "^14.1.0" can still be pinned to 14.1.0 by your lockfile. At the root of the project:

bash
# npm
npm ls next

# pnpm (add -r in a monorepo)
pnpm why next

# yarn
yarn why next

# what the Next.js CLI reports
npx next --version
Compare the result with the table above.
bash
# package-lock.json
grep -A1 '"node_modules/next"' package-lock.json

# pnpm-lock.yaml
grep -E '^  /?next@' pnpm-lock.yaml

# yarn.lock (Yarn 1 and Yarn Berry)
grep -A1 -E '^"?next@' yarn.lock
Your host installs what the lockfile says. In a monorepo, check each app that depends on next.

Then check what production runs. Open your live site, open the browser console and type next.version. It catches the case where the repository is patched but an old container still serves the traffic.

How to check your live app

A version tells you whether the flaw is present. It does not tell you whether a page depends on middleware alone, which is what turns the flaw into a leak. Two checks answer that.

  1. Read each protected page as if middleware did not exist. In app/dashboard/page.tsx, the admin pages, every route handler and every Server Action: is there a session check of its own, such as verifySession(), auth() or getUser(), before data is loaded? If the only check is in middleware.ts, that page is open to this CVE on a vulnerable version, and to the 2026 bypasses on newer ones.
  2. Search your access logs for requests carrying x-middleware-subrequest. The default nginx log format only records the referer and user agent headers, so add $http_x_middleware_subrequest to your log_format. On a self-hosted app, that header arriving from the internet is a probe.

Keybrum runs this check against the live app. It finds the pages that send a signed-out visitor to sign-in, or answer 401 or 403, then requests each one again the way CVE-2025-29927 allows, and as a router prefetch. If the page comes back, the finding shows both requests side by side. It sends only GET requests, keeps a redacted excerpt as proof rather than the page, and runs only on apps whose owner proved ownership.

How to fix CVE-2025-29927

Upgrade. The first fixed versions are 15.2.3, 14.2.25, 13.5.9 and 12.3.5, released between March 17 and March 23, 2025. With the fix, Next.js validates the header against a random id it generates itself and strips it when validation fails. A low-severity follow-up, CVE-2025-30218, let that id leak to third-party hosts that middleware fetched; 15.2.4, 14.2.26, 13.5.10 and 12.3.6 close it, and Cloudflare told its customers to install those.

In November 2026, those versions are a floor. Next.js 14 and older are no longer supported, and the middleware bypasses disclosed in 2026 are fixed only on the 15.5 and 16 lines. Move to the current patch of a supported line:

bash
# Next.js 16 (Active LTS), current patch on November 6, 2026
npm install [email protected]

# Next.js 15 (Maintenance LTS, security releases until January 31, 2027)
npm install [email protected]

# the same with pnpm or yarn
pnpm add [email protected]
yarn add [email protected]
Commit the new lockfile, rebuild and redeploy. Going from 13 or 14 to 15 or 16 is a major upgrade: read the Next.js upgrade guides first.

Next.js 16 renamed middleware to proxy. npx @next/codemod@canary middleware-to-proxy . renames the file and the function. The lesson of this CVE carries over: proxy is a first filter, not the lock.

If you cannot upgrade today: block the header

The advisory's workaround is to stop external requests carrying x-middleware-subrequest from reaching your Next.js server. You cannot do it in middleware, since middleware is what gets skipped. Do it in the reverse proxy or the firewall in front.

nginx
location / {
    # drop the header before the request reaches Next.js
    proxy_set_header x-middleware-subrequest "";

    # repeat the proxy_set_header lines of your server block here
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    proxy_pass http://127.0.0.1:3000;
}
nginx: a header set to an empty string is not passed to the upstream server.
caddy
example.com {
    reverse_proxy 127.0.0.1:3000 {
        header_up -x-middleware-subrequest
    }
}
Caddy: the minus sign deletes the header before the request reaches Next.js.

On Cloudflare, create a custom WAF rule with the expression (len(http.request.headers["x-middleware-subrequest"]) > 0) and the action Block, or Log first to see what it would catch. On the Pro plan and above, you can turn on the managed rule for this CVE instead.

What to do after upgrading

  1. 1

    Confirm production runs the fix

    Redeploy, then type next.version in the console of your live site. On a self-hosted app, make sure the container that serves traffic was rebuilt: an old image keeps the old version running.

  2. 2

    Put the real check next to the data

    Keep middleware for the redirect if you like, and add a session check in every page, route handler and Server Action that loads private data. The Next.js authentication guide says Proxy "should not be your only line of defense in protecting your data".

  3. 3

    Look back at your logs

    If your app was self-hosted on a vulnerable version, search your logs for the header, as far back as they go. If a page with personal data was reached that way, handle it as a data exposure: find out what was shown, and to whom.

  4. 4

    Watch for the next bypass

    Every new kind of request Next.js accepts, such as prefetch URLs and data routes, is one more path a middleware rule can miss. That is how the 2026 advisories below happened. Keep next on the current patch.

tsx
// app/dashboard/page.tsx
import { redirect } from 'next/navigation'
import { verifySession } from '@/lib/dal' // reads and verifies the session cookie

export default async function DashboardPage() {
  const session = await verifySession()
  if (!session) redirect('/login')

  // load only this user's rows
  const projects = await getProjects(session.userId)
  return <Dashboard projects={projects} />
}
This check runs whether middleware ran or not. Do the same in route handlers and Server Actions, which are reachable without the page.

A session check is half of it. Loading only the rows that belong to that session is the other half, or one signed-in user reads another's data: see IDOR and broken access control.

CVE-2025-29927 is the best known of a series. Each one finds a request that reaches a page without matching the middleware rule meant to guard it.

CVEWhat it doesSeverityFixed in
CVE-2024-51479Authorization in middleware based on the pathname could be bypassedHigh, 7.514.2.15
CVE-2025-29927An internal header makes Next.js skip middlewareCritical, 9.115.2.3, 14.2.25, 13.5.9, 12.3.5
CVE-2025-30218The id added by that fix could leak to third-party hostsLow15.2.4, 14.2.26, 13.5.10, 12.3.6
CVE-2026-44573Pages Router with i18n: data requests without a locale skip middlewareHigh, 7.515.5.16, 16.2.5
CVE-2026-44574Crafted query parameters change the dynamic route value while the path still looks the same to middlewareHigh, 8.115.5.16, 16.2.5
CVE-2026-44575App Router segment-prefetch and .rsc URLs are not matched by the middleware ruleHigh, 7.515.5.16, 16.2.5
CVE-2026-45109The 44575 fix did not cover middleware.ts built with TurbopackHigh, 7.515.5.18, 16.2.6
CVE-2026-64642App Router built with Turbopack and a single localeHigh, 8.3 (CVSS 4.0)16.2.11
Severities and versions from the GitHub advisories. The 2026 advisories all give the same workaround: enforce authorization in the page or route itself, not only in middleware.

Other Next.js CVEs work differently: CVE-2024-34351 is a server-side request forgery in Server Actions, and React2Shell runs code on the server. The Next.js security guide covers the framework as a whole, and vibe coding security risks covers what AI-built apps leak most often.

Timeline

DateEvent
February 27, 2025Allam Rachid and Allam Yasser report the flaw to Vercel, first for Next.js 12.x. A second email on March 1 extends it to recent versions.
March 14Vercel's security team escalates the report, and the Next.js team confirms it.
March 17 and 18Next.js 14.2.25, then 15.2.3, ship the fix. GitHub assigns CVE-2025-29927.
March 21The advisory GHSA-f82v-jwr5-mffw and the CVE go public.
March 22Vercel says its customers are not affected. Cloudflare ships a WAF rule and makes it opt-in the same day. Next.js 13.5.9 ships as a backport.
March 23Next.js 12.3.5 ships as a backport.
March 24Akamai deploys a detection rule. Next.js 15.2.4, 14.2.26, 13.5.10 and 12.3.6 fix the follow-up, CVE-2025-30218, whose advisory follows on April 2.
May 11, 2026Three new middleware and proxy bypasses, CVE-2026-44573, CVE-2026-44574 and CVE-2026-44575, fixed in 15.5.16 and 16.2.5.
July 22, 2026CVE-2026-64642, a bypass with Turbopack and a single locale, fixed in 16.2.11.
November 3, 2026Next.js 16.4.5 and 15.5.29, the current patches on the two supported lines.

Questions

Is my Next.js app vulnerable to CVE-2025-29927?

It is if three things are true: next is between 11.1.4 and 15.2.2 without the fix for its line (12.3.5, 13.5.9, 14.2.25 or 15.2.3), you run the server yourself with next start or the standalone output, and middleware is where your login or role check happens. Apps on Vercel, Netlify or Cloudflare Workers, and static exports, were not exposed. Check the version in your lockfile, not the range in package.json.

What is the x-middleware-subrequest header?

An internal header that Next.js added to requests made by middleware itself, so that middleware would not call itself in an endless loop. Before the fix, Next.js also accepted it from outside, and a request carrying it could skip middleware. Fixed versions validate the header and strip it when the check fails.

Is a Next.js app on Vercel affected by the middleware bypass?

No. Vercel's routing runs in a separate system, so the header could not make deployments there skip middleware, and Vercel said its customers were not affected. It still recommends upgrading, and the same code moved to your own server would be exposed.

Does Next.js 16 have this middleware bypass?

Not this one: it was fixed in 15.2.3, months before Next.js 16 came out. Next.js 16 renamed middleware to proxy, and 2026 brought new middleware and proxy bypasses through prefetch URLs, route parameters and locales, fixed in 16.2.5, 16.2.6 and 16.2.11. Run the current patch, 16.4.5 in November 2026.

How do I fix the Next.js auth bypass without upgrading?

Strip or block the x-middleware-subrequest header before requests reach Next.js: in nginx with proxy_set_header x-middleware-subrequest "";, in Caddy with header_up -x-middleware-subrequest, or with a WAF rule. It is a stopgap until you upgrade and add session checks in your pages and routes.

Was CVE-2025-29927 exploited in the wild?

It is not in CISA's Known Exploited Vulnerabilities catalog, and no primary source reports a confirmed breach through it, though Akamai and Datadog both saw probes. Press coverage of a December 2025 campaign called PCPcat lists it, but credits it with running code on servers, which this CVE cannot do on its own. FIRST's EPSS model puts the chance of exploitation in the next 30 days at 0.99, so treat an unpatched self-hosted app as exposed.

Sources

  1. 1.Authorization Bypass in Next.js Middleware (GHSA-f82v-jwr5-mffw), Next.js (GitHub security advisory)
  2. 2.CVE-2025-29927 Detail, NIST National Vulnerability Database
  3. 3.CVE-2025-29927 record, CVE Program
  4. 4.Postmortem on Next.js Middleware bypass, Vercel
  5. 5.Next.js and the corrupt middleware: the authorizing artifact, Allam Rachid (zhero) and Allam Yasser (inzo_)
  6. 6.Vercel Firewall proactively protects against vulnerability with middleware, Vercel
  7. 7.CVE-2025-30218, Vercel
  8. 8.New managed WAF rule for Next.js CVE-2025-29927, Cloudflare
  9. 9.Detecting and Mitigating an Authorization Bypass Vulnerability in Next.js, Akamai
  10. 10.Understanding CVE-2025-29927: The Next.js Middleware Authorization Bypass Vulnerability, Datadog Security Labs
  11. 11.Known Exploited Vulnerabilities Catalog, CISA
  12. 12.Next.js has a Middleware / Proxy bypass in App Router applications via segment-prefetch routes (GHSA-267c-6grr-h53f), GitHub Advisory Database
  13. 13.How to implement authentication in Next.js, Next.js Docs
  14. 14.proxy.js (Migration to Proxy), Next.js Docs
  15. 15.Support Policy, Next.js
  16. 16.November 2026 Security Release, Next.js
  17. 17.Exploit Prediction Scoring System (EPSS), FIRST
  18. 18.ngx_http_proxy_module: proxy_set_header, nginx

Your app is public. So are its mistakes.

Check what any attacker can already see in it, free, in ten seconds. The full attack, with proof and fixes: €49 once, or €29 a month on a plan.

or continue with Google or GitHub