The Great Next.js Middleware Heist of 2025: How a Single HTTP Header Can Bypass Your Auth

Shovon Saha
3 min readMar 25, 2025

--

“It’s not about complex exploits or fancy zero-days. Sometimes it’s just about knowing which door was left unlocked.”

TL;DR (Because I Know You’re Going to Skip Anyway)

  • A critical vulnerability (CVE-2025–29927) in Next.js lets attackers completely bypass your middleware auth with a single HTTP header
  • Affected versions: 11.1.4 through 13.5.6, 14.x before 14.2.25, and 15.x before 15.2.3
  • Next.js apps on Vercel are automatically safe (thanks Vercel! 🙏)
  • Everyone else: upgrade to 14.2.25/15.2.3+ ASAP or block the evil header

The Epic Facepalm Moment

Picture this: You’ve spent weeks meticulously crafting your Next.js app’s authentication system. Your middleware is a fortress — checking session tokens, validating permissions, redirecting unauthorized users. You sleep soundly at night knowing your /admin dashboard is secure.

Meanwhile, an attacker is sitting in their pajamas, adding a single HTTP header to their request and waltz right past all your security like they own the place:

GET /admin
Host: your-awesome-app.com
X-Middleware-Subrequest: middleware

That’s it. That’s the entire hack. One header and your fortress crumbles.

How Is This Even Possible?!

The vulnerability hinges on a seemingly innocent internal mechanism in Next.js. The framework uses the x-middleware-subrequest header to prevent infinite middleware loops. When Next.js sees this special header, it basically says, "Oh, you've already been through middleware? Cool, I'll just let you through!"

The problem? Next.js never checks if the request actually came from middleware or if some sneaky user just added the header themselves.

It’s like having a super-secure door with retinal scanners, but then putting up a sign that says, “If you say the secret phrase ‘I’ve already been checked,’ the guard will let you right in.”

Code Time: What’s Actually Happening

In the heart of Next.js, there’s some code that looks roughly like this:

// Simplified version of what's happening inside Next.js
const subreq = request.headers["x-middleware-subrequest"];
const subrequests = typeof subreq === "string" ? subreq.split(":") : [];
if (subrequests.includes(middlewareInfo.name)) {
// "Oh, you've been through middleware already? Come right in!"
return NextResponse.next();
}

For different Next.js versions, the magic value varies slightly:

  • For versions before 12.2: x-middleware-subrequest: pages/_middleware
  • For versions 12.2 and later: x-middleware-subrequest: middleware
  • For projects with a /src structure: x-middleware-subrequest: src/middleware
  • For newer versions with recursion depth: x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware

Fix It Now: Your Action Plan

Option 1: The “I Have My Life Together” Solution

Update your Next.js version:

  • For Next.js 15.x: update to version 15.2.3 or later
  • For Next.js 14.x: update to version 14.2.25 or later
# For npm
npm install next@15.2.3 react@latest react-dom@latest
# For yarn
yarn add next@15.2.3 react@latest react-dom@latest
# For pnpm
pnpm add next@15.2.3 react@latest react-dom@latest

Option 2: The “I Can’t Update Right Now” Solution

Block the evil header at different levels:

Using Nginx:

# In your nginx.conf
proxy_set_header x-middleware-subrequest "";

Using Apache:

# In your .htaccess or Apache config
RequestHeader unset x-middleware-subrequest

Using Express (with custom server):

// In your custom server.js
app.use((req, res, next) => {
delete req.headers['x-middleware-subrequest'];
next();
});

Using AWS Load Balancer:

Set up a rule to strip or block requests with the x-middleware-subrequest header.

The “Am I Actually Vulnerable?” Test

  1. Do you use Next.js middleware for auth, redirects, or security headers?
  2. Is your Next.js version between 11.1.4 and 15.2.2?
  3. Are you self-hosting (not on Vercel)?

If you answered yes to all three, congratulations! You’re vulnerable. Fix it now.

Final Thoughts

This vulnerability is a reminder that even the most sophisticated security systems can be undermined by seemingly small oversights. It’s not about the ninety-nine doors you locked; it’s about the one you left open.

So update those dependencies, block those headers, and maybe pour yourself a strong coffee (or something stronger) while contemplating the fragility of web security.

Stay safe out there, fellow developers!

Disclaimer: I’m just a developer trying to help other developers. Always refer to official security advisories and documentation for the most accurate information.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Shovon Saha
Shovon Saha

Written by Shovon Saha

Creating art in multiple forms from code to music production with photography and videography in between.

No responses yet

Write a response