Next.js CVE-2025-29927 Reproduction Notes
Next.js CVE-2025-29927 in Vulhub: how x-middleware-subrequest affects middleware authorization, with an initial analysis of the mechanism.
1/15/2024
A Brief Introduction to Next.js
I see many blogs and other sites using Next.js.
Next.js is an open-source frontend development framework based on React, used to build modern web applications, especially applications using server-side rendering (SSR) and static site generation (SSG). It is developed and maintained by Vercel (formerly Zeit).
Next.js backend services can indeed run in two modes: Node.js Runtime and Edge Runtime.
Edge computing
Here, let’s take a closer look at Edge Functions (edge functions / edge computing).
An Edge Function is a small function that runs on a server closer to the user. It responds quickly with low latency and is suited to providing the “first response” to a request.
Edge computing is a distributed-computing paradigm. It pushes computation and data storage closer to where they are needed — the source of data generation or the end user. This contrasts with traditional centralized cloud computing, where all data is sent to a distant, large data center for processing.
| Platform | Product name |
|---|---|
| Vercel | Edge Functions |
| Cloudflare | Workers |
| Netlify | Edge Functions |
| AWS | Lambda@Edge |
| Deno | Deno Deploy |
| Bun | Bun Edge Runtime (experimental) |
Vulnerability reproduction
Reproducing the environment
Versions earlier than Next.js 14.2.25 and 15.2.3 are affected.
I reproduced it here using a Vulhub environment.
vulhub/next.js/CVE-2025-29927 at master · vulhub/vulhub
The environment opens to a login page.

If we log in with the default administrator username and password,
we can see that we enter the administration panel.

We analyze it in Yakit.

We add the following to the request:
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware
The result shows that we bypassed authorization and authentication.


Vulnerability principles
How Next.js handles a special internal HTTP header, x-middleware-subrequest.
Purpose of the
**x-middleware-subrequest**header: This header is intended for internal use by the Next.js framework, mainly to prevent middleware from entering an infinite recursive loop while handling requests. When middleware internally triggers a request to another URL that might also require the same middleware, this header tracks the call level or state.
Therefore, our bypass mechanism works as follows:
When a Next.js application receives a request with a carefully crafted **x-middleware-subrequest** header, the framework incorrectly determines that the request appears to have already been processed by the middleware (or has reached the maximum recursion depth), and decides to skip the middleware logic that should have run.
As a result, we can access resources that should be protected.
Returning to the payload, I have seen some sources say:
In some versions, Next.js checks the value of the _x-middleware-subrequest_ header to prevent infinite recursion. It counts the number of times the header value contains the current middleware name. The default maximum recursion depth (_MAX_RECURSION_DEPTH_) is 5.
curl -i -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" http://127.0.0.1:3000
So when Next.js receives this request,
it assumes there is no need to execute the middleware again, skips its processing logic, and passes the request to the next stage.
Vulnerability detection
See THM for details.