CVE-2025-29927 – Authorization Bypass Vulnerability in Next.js: All You Need to Know
On March 21st, 2025, the Next.js maintainers announced a new authorization bypass vulnerability – CVE-2025-29927. This vulnerability can be easily exploited to achieve authorization bypass. In some cases – exploitation of the vulnerability can also lead to cache poisoning and denial of service.
Which versions of Next.js are affected?
Next.js 15.x – from version 15.0.0 up to and including 15.2.2.
Next.js 14.x – from version 14.0.0 up to and including 14.2.24.
Earlier Next.js versions – from version 11.1.4 up to and including 13.5.6.
Attack scenarios for CVE-2025-29927
In order for the vulnerability to be exploited at all, the victim Next.js server must use a Next.js Middleware. This consists of including a middleware.js
or middleware.ts
file ( _middleware.js
or _middleware.ts
for older versions of Next.js). This file defines and exports the middleware
function that holds the logic run when each HTTP request is received.
Authorization bypass
This is the most likely exploitation scenario for CVE-2025-29927.
This scenario is relevant when the victim Next.js server uses the Middleware feature to perform authorization (and the underlying application doesn’t use any other authorization layers).
Authorization middleware scenario without CVE-2025-29927 exploitation
Authorization middleware scenario with CVE-2025-29927 exploitation
Denial of service via cache poisoning
Next.js middleware can also help with localizing websites. For example, the middleware can automatically redirect users based on their location—say, adding /en
for English speakers or /fr
for French visitors. If someone exploits CVE-2025-29927 and bypasses the middleware that performs these redirects – instead of landing on a localized page, they will land on the website root (/
), for which the developers never built a page. The result? A 404 error or a 500 server error, depending on the configuration.
If the site uses a CDN or another caching layer, these error responses can be stored and served to future visitors. Once cached, legitimate users might see broken pages globally. This creates a self-inflicted outage, crippling availability without changing a single line of code.
Redirector middleware scenario without CVE-2025-29927 exploitation
Redirector middleware scenario with CVE-2025-29927 exploitation
Understanding Next.js Middleware
Next.js middleware is a powerful feature introduced in Next.js v12 that allows developers to execute code before a request is completed. Operating on the edge, closer to the user than traditional server-side code, middleware can modify response headers, rewrite or redirect requests, and most importantly- implement authentication and authorization checks.
Middleware in Next.js runs before rendering and can be configured to execute on specific paths through matcher configurations.
A few example use-cases for Next.js middleware are:
- Verifying authentication tokens
- Implementing role-based access control
- Redirecting unauthenticated users
A typical Next.js middleware implementation that performs authentication might look like this:
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
// Get the user token from the cookies
const token = request.cookies.get('token').value
// Validate the user is authenticated
const isAuthenticated = validateToken(token)
// If not authenticated, redirect to login
if (!isAuthenticated) {
return NextResponse.redirect(new URL('/login', request.url))
}
// Continue to protected route if authenticated
return NextResponse.next()
}
// Configure which routes use this middleware
export const config = {
matcher: ['/dashboard/:path*', '/settings/:path*'],
}
CVE-2025-29927 technical analysis
CVE-2025-29927 exposes a critical flaw in how Next.js middleware processes certain types of requests, leading to potential authentication and authorization bypasses.
This vulnerability affects applications using middleware for access control in certain configurations.
The vulnerability stems from the inconsistent handling by Next.js of the custom x-middleware-subrequest
headers. When this header is included in requests to protected routes, Next.js incorrectly allows the request to bypass middleware execution entirely. The header forces the Next.js runtime to skip the middleware evaluation phase while still processing the underlying route handler.
To exploit this vulnerability, an attacker simply needs to add the x-middleware-subrequest
header to their HTTP requests when accessing protected resources. For example, a request to /api/admin/users
that would normally be blocked by middleware authorization checks will be processed normally when this header is present. The server processes the request as though middleware has already run and approved it, creating a complete security bypass. This header manipulation can be easily implemented using browser developer tools, curl commands, or simple scripts.
The vulnerable code on the latest version that is vulnerable (v15.2.2) is as follows:
export const run = withTaggedErrors(async function runWithTaggedErrors(params) {
const runtime = await getRuntimeContext(params)
const subreq = params.request.headers[`x-middleware-subrequest`] [1]
const subrequests = typeof subreq === 'string' ? subreq.split(':') : [] [2]
const MAX_RECURSION_DEPTH = 5
const depth = subrequests.reduce( [3]
(acc, curr) => (curr === params.name ? acc + 1 : acc),
0
)
if (depth >= MAX_RECURSION_DEPTH) { [4]
return {
waitUntil: Promise.resolve(),
response: new runtime.context.Response(null, {
headers: {
'x-middleware-next': '1',
},
}),
}
}
The x-middleware-subrequest
header is taken from the request on [1].
It’s then split using the :
delimiter on [2], and ran through a reduce function that counts how many items in this array (subrequests
) match the middleware filename on [3].
If this number is equal or more than MAX_RECURSION_DEPTH
(which is 5
) on [4], it then bypasses the functionality of the middleware and redirects to its route.
Attack header possible values
As explained before, the vulnerable header name is x-middleware-subrequest
. The value assigned to it depends on Next.js because it is set according to the value of middlewareInfo.name
which is essentially the path to the middleware.js
or middleware.ts
file.
Before version 12.2, the middleware file was actually named _middleware.js
/_middleware.ts
and could have been located at any level of the subdirectory we’re trying to access. In our case, we’re trying to access /admin/dashboard
which means middlewareInfo.name
could have been pages/_middleware
or pages/admin/_middleware
. Had we set dashboard
to be a directory with an index.js
file, it could have also been pages/admin/dashboard/_middleware
.
For example, if we had been using a Next.js version prior to 12.2 with our PoC code, we would have needed to move middleware.js
to the pages
directory and rename it _middleware.js
, and our “malicious” HTTP request would be:
GET /admin/dashboard HTTP/1.1
x-middleware-subrequest: pages/_middleware
Since version 12.2 and until version 13, the middleware file has to exist at the root of the project and has to be named middleware.js/middleware.ts
. So for attacking these versions of Next.js, the payload for the header would just be middleware
– and we know for a fact that it is in the root directory.
If we had been using a Next.js version between versions 12.2 and 13, our “malicious” request would change as follows:
GET /admin/dashboard HTTP/1.1
x-middleware-subrequest: middleware
From version 13 of Next.js and onwards, the recursion check we saw before was implemented – which means that an attacker would have to set the malicious header to be middleware:middleware:middleware:middleware:middleware
, to simulate 5 levels of recursion.
Since our PoC is on this version, this is a snippet from the request we used:
GET /admin/dashboard HTTP/1.1
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware
Keep in mind that at all stages, the Middleware code could have been in a src
directory – which would mean prepending src
to the values presented above would be necessary for exploiting. For example, if we had put our PoC code in a src
directory, our payload would have needed to be:
GET /admin/dashboard HTTP/1.1
x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middleware.
Exploiting CVE-2025-29927
As always, it’s best to see a full exploitation of the vulnerability to understand which Next.js instances would be vulnerable.
We set up our own PoC website with the following working tree:
├── middleware.js
├── package-lock.json
├── package.json
└── pages
├── admin
│ └── dashboard.js
└── index.js
First of all, our login page:
Resolving CVE-2025-29927
Version Upgrade
The best way to resolve CVE-2025-29927 is to upgrade your version of Next.js to one of the fixed versions –
- 15.2.3
- 14.2.25
Make sure to identify any versions that might be at risk, from 11.1.4 up to and including 13.5.6, 14.2.24, and 15.2.2, and update them to this newly fixed version.
Blocking the vulnerable header in the Web Server
If upgrading is not an option, the vulnerability can be mitigated by instructing your web server to strip the `x-middleware-subrequest` from incoming requests –
In Apache, add the following directive to your .htaccess
file (mod_headers
must be installed and enabled) –
<IfModule mod_headers.c> RequestHeader unset x-middleware-subrequest </IfModule>
In NGINX, edit your nginx.conf
file and add the following proxy_set_header
directive to your server block –
proxy_set_header x-middleware-subrequest "";
For example –
server { listen 80; server_name your_domain.com; location / { proxy_set_header x-middleware-subrequest ""; } }
In Express.js, add the following directive to your JavaScript source code –
// Middleware to remove the x-middleware-subrequest header app.use((req, res, next) => { delete req.headers['x-middleware-subrequest']; next(); });
Blocking the vulnerable header with a WAF
If upgrading is not an option, the vulnerability can be mitigated by using a Web Application Firewall to block requests that contain the x-middleware-subrequest`
HTTP Header.
Resolving CVE-2025-29927 with JFrog Xray and JFrog Advanced Security
As always, JFrog Security Essentials (Xray) can be used to identify every occurrence of Next.js across your entire codebase and compiled artifacts, including Docker containers, repository packages, and even standalone binaries.
Additionally, JFrog Advanced Security has been updated with a Contextual Analysis scanner that automatically checks whether your Next.js deployment is truly vulnerable to CVE-2025-29927 by checking whether a Next.js Middleware is used.
JFrog Platform: JFrog Contextual Analysis for Next.js’s CVE-2025-29927 (Click image for full-size)
Check out the JFrog Security Research center for the more information about the latest CVEs and vulnerabilities and fixes.