CVE-2025-29927 Explained: The Next.js Middleware Authorization Bypass
When a vulnerability lands in a framework as widely deployed as Next.js, the impact is rarely theoretical. CVE-2025-29927 is a high-severity middleware authorization bypass that, in the wrong circumstances, can let an attacker reach “protected” pages and API routes as if they were already authenticated.
At the heart of the issue is a subtle trust mistake: Next.js middleware includes internal safeguards to prevent infinite loops during rewrites, and those safeguards relied on an HTTP header that should never have been trusted from an external client. With a single spoofed header, an attacker could convince the runtime that middleware had already executed “enough times,” causing the framework to skip the developer’s middleware logic entirely.
This article walks through the attack surface, the root cause, how the bypass works in practice, what changed in the patch, and how to harden applications with defense-in-depth so a middleware failure is never a single point of compromise.
The Role of Middleware in Next.js Security and Routing
Next.js middleware runs before a request reaches the route handler or page rendering logic. Many teams use it for:
- Authentication and authorization routing
- Redirecting unauthenticated users to
/login - Blocking access to
/adminor sensitive API endpoints - Enforcing role-based access control (RBAC) at the edge
- Redirecting unauthenticated users to
- URL rewrites and server-side redirects
- Security header injection
- Content Security Policy (CSP)
- Other response hardening headers
- Caching behavior and request shaping
Middleware is attractive because it is fast, centralized, and easy to reason about. But the same properties make it tempting to treat middleware as “the” authorization layer.
CVE-2025-29927 demonstrates why that assumption is risky. If middleware is bypassed:
- Requests can reach routes that developers believed were inaccessible.
- Security headers that were injected in middleware may be missing.
- In some deployments (especially those involving CDNs and caching rules), the bypass can interact with caching and rewriting in ways that create cache poisoning or availability issues.
The uncomfortable truth is that middleware is a powerful optimization layer, but it is not a guarantee. When the framework’s middleware execution can be short-circuited, an app that relies on middleware alone becomes brittle.
CVE-2025-29927 Explained: The Next.js Authorization Bypass
CVE-2025-29927 is an authorization bypass affecting Next.js middleware execution. It was reported by security researchers Rasheed Alam and Yaser Alam of Zhero Web Security.
Next.js uses an internal header to track recursive middleware subrequests during rewrites. If the framework believes the request has already passed through middleware too many times, it stops running middleware to avoid infinite loops.
The vulnerability existed because Next.js trusted that internal header even when it came from the public internet.
In other words, an attacker could send a request that pretends to be an internal subrequest that has already “hit the recursion limit,” and the runtime would skip middleware.
Root Cause Analysis: HTTP Header Trust Boundary Failures
Middleware can rewrite to another route, and that new route can itself be covered by middleware. Without guardrails, rewrites could accidentally create a loop.
To prevent infinite recursion, Next.js added an internal mechanism that tracks how many times middleware has been invoked during a single request cycle. It does this with a header:
x-middleware-subrequest
The internal engine parses the header’s value, counts how many times it references the middleware name/path, and treats that as a “depth” indicator.
Prior to the patch, the logic effectively did:
- Read
x-middleware-subrequest. - Split it by
:. - Count matching entries that represent the middleware identifier.
- If computed depth is at or above a hardcoded maximum (commonly
5), bail out.
That bailout is a safety measure for recursion, but it had an unintended consequence: it returned a response path that skipped developer-defined middleware.
This is a textbook trust boundary issue:
- The header is intended for internal use.
- HTTP headers are trivially attacker-controlled.
- Without server-side validation, an attacker can impersonate internal traffic.
Once a framework feature starts behaving differently based on a header, that header becomes a security-sensitive input.
Exploit Mechanics: Bypassing Next.js Middleware Controls
Exploitation is simple because it does not require memory corruption, timing, or complex gadget chains. It uses a single request with a crafted header.
Assume an application tries to protect: /api/sensitive-data
In a normal flow:
- An unauthenticated request triggers middleware.
- Middleware redirects to
/loginor returns401.
With the exploit, the attacker sends the same request but adds x-middleware-subrequest in a format that makes Next.js compute the recursion depth as “maxed out.”
A typical pattern is repeating the middleware identifier multiple times:
GET /api/sensitive-data HTTP/1.1
Host: target-app.com
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware
When Next.js believes the depth is already at the limit, it stops executing middleware and the request continues to the underlying route.
The exact header value depends on how middleware is represented in that Next.js version:
- Next.js 12.2 and above
- Middleware is centralized to the root or
src/. - Identifiers often look like
middlewareorsrc/middleware.
- Middleware is centralized to the root or
- Before Next.js 12.2
- Middleware used
_middlewarefiles and could be nested, for examplepages/admin/_middleware. - Bypassing nested middleware could require matching the expected path string.
- Middleware used
This is an important operational detail for both attackers and defenders: detection and WAF rules should not assume a single exact header value.

A Real-World Walkthrough
Let's look at a practical example from a vulnerable environment to see exactly how this behaves from an attacker's perspective.
Step 1: Reconnaissance
First, we encounter a standard login page protecting the application. By using browser fingerprinting tools like Wappalyzer, we can confirm the underlying tech stack. As seen below, the target application is running Next.js 12.2.5, which falls directly within the vulnerable version range.


Step 2: Establishing the Baseline
Next, we attempt to access a protected route without valid credentials. Intercepting this initial GET request in an HTTP proxy, we see the expected, secure behavior: the Next.js middleware successfully catches our unauthenticated request and issues a 307 Temporary Redirect, pushing us back to the /login page.

Step 3: Executing the Bypass
Now, we apply the CVE-2025-29927 exploit. We send the exact same request back to the server, but this time, we manually inject the malicious header: x-middleware-subrequest: middleware.
As shown in the final response, the server immediately returns a 200 OK. The Next.js framework skips the middleware execution loop entirely, serving the protected HTML content and completely bypassing the login mechanism.

Using Curl
A minimal one-liner for testing a protected endpoint might look like:
curl -i -H "x-middleware-subrequest: middleware" http://TARGET_IP:3000/protected
Some deployments require the identifier repeated multiple times to reach the recursion threshold, while others may be impacted with fewer repetitions depending on how middleware is invoked.
Patch Analysis: Moving to Server-Side Header Validation
Next.js addressed the flaw in:
- 15.2.3
- 14.2.25
- 13.5.9
- 12.3.5

The core fix is straightforward: the framework now verifies that the subrequest header is legitimate.
In patched versions, Next.js generates a cryptographically random server-side value and stores it in a global symbol:
globalThis[Symbol.for('@next/middleware-subrequest-id')]

When handling requests, Next.js checks that:
If x-middleware-subrequest is present, there must also be a correct x-middleware-subrequest-id matching the server-generated value.
If the ID is missing or incorrect, Next.js deletes the attacker-controlled subrequest header before the middleware routing logic sees it.
This turns an attacker-controlled header into something that is only meaningful when it is paired with a server-only secret. It’s a classic “capability token” approach:
- The header becomes an internal implementation detail again.
- External clients can send the header, but it no longer changes behavior.
Remediation Strategies and Defense-in-Depth Architecture
Patching Next.js is the priority. But mature remediation also assumes:
- Patches can take time to deploy.
- Misconfigurations and regressions happen.
- Another framework bug will exist tomorrow.
Patch immediately (primary remediation)
Upgrade to a fixed version (or newer). If you run a fleet of services, ensure this is enforced across all environments, including staging and ephemeral preview deployments.
Add edge protection while you patch (WAF / proxy mitigation)
If you cannot patch immediately, block or strip internal Next.js headers at your edge:
x-middleware-subrequestx-middleware-override-headers
This can be done at a reverse proxy, load balancer, or WAF.
Managed platforms often roll out temporary mitigations quickly, but self-hosted environments need explicit configuration.
Detection engineering: find exploitation attempts
Log analysis
If your access logs include request headers, search for:
- Presence of
x-middleware-subrequest - Unusual repeated tokens separated by
:
For example, some servers can be configured to log the header explicitly. In Apache-style formatting:
LogFormat "%h %l %u %t \\"%r\\" %>s %b \\"%{Referer}i\\" \\"%{User-Agent}i\\" \\"%{x-middleware-subrequest}i\\"" custom
Network detection (IDS/NSM)
If you operate packet-based monitoring, alerting on the header itself is often useful.
A simple Snort v2 rule pattern might inspect raw bytes for the header name:
alert tcp any any -> any any (msg: "HTTP 'x-middleware-subrequest' header detected, possible CVE-2025-29927 exploitation"; content:"x-middleware-subrequest"; rawbytes; sid:10000001; rev:1)
For deeper network visibility, Zeek can be extended to log and alert when the header appears.
The architectural lesson: never let middleware be your only auth layer
The most important long-term fix is not in a version bump. It is in application design.
Middleware is excellent for:
- Fast redirects
- Coarse-grained gating
- Request shaping
But for sensitive assets, authorization must be enforced again at the point of data access:
- In API controllers
- In server actions
- In database query layers
- In service-to-service authorization checks
A good rule of thumb is:
- If bypassing middleware would expose sensitive data, the backend is missing a required authorization check.
The Real-World Enterprise Impact of Middleware Bypasses
This issue is most damaging when three conditions line up:
- The application uses middleware as the primary authorization layer.
- Protected routes do not re-validate session and permissions server-side.
- There are undocumented or forgotten endpoints that were assumed safe “because middleware protects them.”
This is where real-world attackers thrive. They look for the gap between what engineers believe is protected and what is actually enforced at the data boundary.
How Jsmon Helps: Securing the Hidden API Attack Surface
Even with a patch available, organizations often need time to roll changes out safely. During that window, risk is heavily influenced by how visible and discoverable sensitive endpoints are.
Jsmon helps by continuously mapping your external web attack surface through analysis of frontend JavaScript bundles and source maps. By extracting routes and API paths that appear in client-side code, it can uncover:
- Shadow APIs that were never documented
- Forgotten internal endpoints that drifted into production
- Routes that rely on optimistic middleware checks
That visibility makes it easier to prioritize:
- Which endpoints must be patched and re-validated first
- Where to apply targeted WAF rules
- What needs strict server-side authorization immediately
Conclusion
CVE-2025-29927 is a reminder that framework middleware, no matter how convenient, is not a security boundary you can safely bet everything on. The underlying flaw was simple: an internal header used for recursion tracking was trusted from external requests, allowing attackers to short-circuit middleware execution.
The immediate response is clear: upgrade to a patched Next.js version and consider temporary edge controls that block internal headers. But the lasting takeaway is architectural: the backend must always be prepared to say “no” on its own. If a request reaches an API route or server component, that code must validate authentication and authorization as if middleware did not exist.
References and further reading
- Official CVE record: https://nvd.nist.gov/vuln/detail/CVE-2025-29927
- Zhero Web Security research: https://zhero-web-sec.github.io/research-and-things/nextjs-and-the-corrupt-middleware
- Assetnote analysis: https://www.assetnote.io/resources/research/doing-the-due-diligence-analyzing-the-next-js-middleware-bypass-cve-2025-29927
- ProjectDiscovery blog: https://projectdiscovery.io/blog/nextjs-middleware-authorization-bypass
- Wiz vulnerability database: https://www.wiz.io/vulnerability-database/cve/cve-2025-29927