
Does Next.js need a WAF?
A WAF can protect your Next.js app from passive scanning as well as active exploitation of known vulnerabilities. If you need to be PCI DSS v4.0 compliant then a WAF is required, but what about other types of application?
How to detect Next.js middleware bypass exploits (CVE-2025-29927 & CVE‑2024‑51479) in request logs and using Arcjet for incident forensics.
At Arcjet, we found the recent Next.js middleware bypass vulnerabilities (CVE-2025-29927 & CVE‑2024‑51479) especially relevant - not only are we Next.js users ourselves, but we wanted to see how our own security SDK could help Next.js users manage incident response.
Authorization bypasses rank among the most critical security threats because they allow attackers to enter areas of an application that should remain off-limits. Given that Next.js is one of the most popular JavaScript frameworks and using middleware for authentication is a common pattern, there is a high chance of users being affected these vulnerabilities.
In this post, we’ll examine both of these vulnerabilities and walk through how to identify suspicious patterns to determine if you were affected.
For those already using Arcjet, we’ll also discuss how you can leverage our platform to confirm whether your applications were exploited. Our security SDK integrates with your application’s middleware (or directly inside routes), providing real-time inspection of every incoming HTTP request. This gives us the ability to search for attack signatures in past requests.
x‑middleware‑subrequest
GHSA-f82v-jwr5-mffw (CVE-2025-29927) is a critical Next.js vulnerability that lets attackers bypass middleware authorization checks by providing a crafted x‑middleware‑subrequest
header. It affects all Next.js versions released after 11.1.4, with patches now available in 12.3.5, 13.5.9, 14.2.25, and 15.2.3.
While outright blocking x‑middleware‑subrequest
can stop the exploit, many services legitimately rely on the header for internal requests, as Cloudflare discovered when they attempted a blanket block that had to be rolled back.
Any mitigation that drops this header risks breaking valid functionality, underscoring the need for a more targeted fix, and highlighting a classic problem with generic, network-level WAFs.
Once you apply the patch (or block requests with the header), the question turns to whether or not you were affected. Because the vulnerability dates back to code introduced in 2022 (Next.js > 11.1.4), it’s crucial to search historical logs for requests containing a suspicious x‑middleware‑subrequest
header.
Even though CVE‑2025‑29927 was only recently disclosed, there was a lag in releasing patches (and then announcing the vulnerability). Patch adoption takes time and real-world exploitation has been possible for several years - zero-day vulnerabilities often circulate in underground markets long before they’re officially revealed. This means it's possible to have been affected for some time.
The exploit signature for CVE-2025-29927 is very simple and depends on the version of Next.js you’re using. As explained in the disclosure writeup, we can look for specific payloads:
/admin
where the x-middleware-subrequest
header contains pages/_middleware
or pages/admin/_middleware
x-middleware-subrequest
header containing middleware
or src/middleware
.MAX_RECURSION_DEPTH
constant set to 5
e.g. requests with a x-middleware-subrequest
header containing middleware:middleware:middleware:middleware:middleware
or src/middleware:src/middleware:src/middleware:src/middleware:src/middleware
Any requests matching these signatures could indicate compromise.
Looking further back, another critical middleware flaw, GHSA-7gfc-8cq8-jh5f / CVE-2024-51479, emerged in December 2024. Affecting versions from 9.5.5 up to 14.2.14, Next.js was patched in 14.2.15.
This issue occurs when the middleware’s authorization logic depends on the pathname: the middleware inadvertently allows access to the top‑level route (/admin
) even when sub-paths like /admin/users
are correctly matched.
In the snippet below (adapted from Herodevs), all requests to paths under /admin
with the missing authorization
header should be blocked.
However, this vulnerability meant that while requests to /admin/users
are denied, requests to /admin
would be allowed. If your middleware had similar logic, any sensitive pages at top-level URLs could be accessed.
import { NextResponse } from 'next/server';
export function middleware(request) {
const { pathname } = request.nextUrl;
// Simulate authorization check: block access to /admin unless a condition is met
if (pathname.startsWith('/admin') && !request.headers.get('authorization')) {
return new Response('Unauthorized', { status: 401 });
}
return NextResponse.next();
}
export const config = {
matcher: ['/admin/:path*', '/admin'],
};
This vulnerability hinges on two factors:
/admin
) where the middleware is checking for the pathname. Only the exact root path is exposed, not its sub-routes (like /admin/users
).authorization
(plus the pathname check above) but it could be any other header.As with CVE‑2025‑29927, any application that relied solely on middleware for authorization checks would have been vulnerable. If you run the check (or additional checks) in the routes themselves then you would have had another layer of security. Middleware is good for running initial checks and redirecting users to an authentication flow, it is a good idea to perform further authorization checks in each route.
To confirm whether you were exposed, find any requests to top-level protected paths (e.g., /admin
) that lacked the expected authorization header (like authorization
or x-auth-token
). If those requests bypassed your middleware without triggering an error, you were likely vulnerable.
When conducting an incident analysis, it’s important to be able to answer questions like: was I affected? How long was I affected for? What data was accessed? The answers to these determine what kind of legal disclosures you need to make and how you inform customers.
If you don’t have request logs then how do you know if you were impacted?
Arcjet analyzes and reports granular request metadata such as paths and headers (though sensitive headers like authorization
are redacted and the request body is never sent outside your environment). By installing Arcjet, if (when) a new vulnerability surfaces you’ll have detailed request history to confirm potential exploit attempts. Request logs are available to all Arcjet users, although retention time depends on your pricing plan.
If you need help with determining if you are affected (or have ever been affected) by these or other vulnerabilities, reach out to our support team.
A WAF can protect your Next.js app from passive scanning as well as active exploitation of known vulnerabilities. If you need to be PCI DSS v4.0 compliant then a WAF is required, but what about other types of application?
Nosecone is an open source library to set security headers like Content Security Policy (CSP) and HTTP Strict Transport Security (HSTS) on Next.js, SvelteKit, and other JavaScript frameworks using Bun, Deno, or Node.js. Security headers as code.
Server actions are an elegant way to handle simple functions for common actions like form submissions, but they're a public API so you still need to consider security.
Get the full posts by email every week.