Back to Blog
high SEVERITY8 min read

How Middleware and Proxy Bypass happens in Next.js App Router and how to fix it

CVE-2026-64642 is a high-severity authentication bypass vulnerability in Next.js that affects App Router applications using Turbopack with a single locale configuration. The flaw allows attackers to circumvent middleware and proxy security controls, potentially gaining unauthorized access to protected routes. Upgrading from Next.js 16.2.7 to 16.2.11 closes the vulnerability entirely.

O
By Orbis AppSec
Published August 26, 2026Reviewed August 26, 2026

Answer Summary

CVE-2026-64642 is a high-severity middleware and proxy bypass vulnerability (CWE-287) in Next.js versions prior to 16.2.11, affecting App Router applications that use Turbopack and a single locale. Attackers can craft requests that skip middleware execution entirely, bypassing authentication and authorization checks enforced at the middleware layer. The fix is a dependency upgrade from `next@16.2.7` to `next@16.2.11` in `package-lock.json`, which patches the internal routing logic responsible for the bypass.

Vulnerability at a Glance

cweCWE-287
fixUpgrade next from 16.2.7 to 16.2.11 in package-lock.json
riskUnauthenticated access to routes protected by Next.js middleware
languageJavaScript / TypeScript
root causeTurbopack's single-locale routing path skips middleware execution in the App Router
vulnerabilityMiddleware / Proxy Authentication Bypass

The Vulnerability at a Glance

Field Detail
CVE CVE-2026-64642
Severity High
Affected package next < 16.2.11
Root cause Middleware skipped in Turbopack + single-locale App Router path
Fix Upgrade next to 16.2.11
CWE CWE-287 — Improper Authentication

Introduction

The package-lock.json in this project pinned next at ^16.2.6, which resolved to 16.2.7 at install time. That version contains a critical flaw in how the Turbopack dev/build pipeline handles routing when exactly one locale is configured in the Next.js App Router. Under those conditions, the internal routing code takes a code path that silently skips middleware execution — meaning every middleware.ts or middleware.js file in the project becomes a dead letter for the affected requests.

For any application that gates protected pages behind middleware-level authentication (a very common Next.js pattern), this is a direct authentication bypass: an attacker who knows the right request shape can walk straight past the auth check and land on a route they were never meant to reach.


The Vulnerability Explained

What Next.js Middleware Is Supposed to Do

Next.js middleware runs before a request reaches a page, layout, or API route. Developers use it to:

  • Redirect unauthenticated users to /login
  • Enforce role-based access control across a route group
  • Apply geo-blocking or rate limiting uniformly
  • Rewrite or proxy requests to backend services

A typical middleware.ts looks like this:

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const token = request.cookies.get('session')?.value;
  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  return NextResponse.next();
}

export const config = {
  matcher: ['/dashboard/:path*', '/admin/:path*'],
};

The security model assumes this function always runs for matched paths. CVE-2026-64642 breaks that assumption.

The Specific Trigger Conditions

The bypass activates when all three of the following are true:

  1. The project uses the App Router (the app/ directory introduced in Next.js 13+)
  2. Turbopack is enabled (via next dev --turbo or the turbopack config key)
  3. The i18n configuration specifies exactly one locale

When these conditions align, Turbopack's internal route resolver takes a fast-path branch that omits the middleware invocation step. The result is that requests matching the middleware matcher pattern bypass the function entirely and are served directly.

Why This Specific Configuration Is Common

Single-locale Turbopack setups are not edge cases. Many teams:

  • Enable Turbopack for faster local development and CI builds
  • Add a single defaultLocale to next.config.js for future i18n readiness without actually serving multiple languages yet
  • Rely heavily on middleware for JWT or session-cookie authentication

This combination is entirely reasonable and well-documented in the Next.js guides, which makes the silent bypass especially dangerous — developers would have no reason to suspect their middleware wasn't running.

The Vulnerable Package Version

The package-lock.json before the fix contained:

"node_modules/@next/env": {
  "version": "16.2.7",
  "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.7.tgz",
  "integrity": "sha512-tMJizPlj6ZYpBMMdK8S0LJufrP4QTdR6pcv9KQ/bVETPAmg0j1mlHE9G2c38UyGHxoBapgwuj7XjbGJ2RcDFOg=="
}

And the top-level dependency was pinned to:

"next": "^16.2.6"

Because ^16.2.6 allows any 16.2.x release, npm install resolved this to 16.2.7 — the vulnerable version.

Attack Scenario

Consider a Next.js application with:

  • A /dashboard route group containing sensitive user data
  • A middleware.ts that checks for a valid session cookie and redirects to /login if absent
  • Turbopack enabled in next.config.js
  • i18n: { locales: ['en'], defaultLocale: 'en' } in next.config.js

An attacker who knows (or guesses) the application's framework and configuration can send a direct GET /dashboard request without any session cookie. On a non-vulnerable Next.js version, the middleware intercepts this and returns a 302 redirect to /login. On 16.2.7 with Turbopack and a single locale, the middleware function never fires — the request reaches the app/dashboard/page.tsx render function directly and the page is served in full.

No credentials. No tokens. No exploit code. Just a plain HTTP request.


The Fix

What Changed in package-lock.json

The fix is a targeted dependency upgrade. The diff shows two categories of change:

1. Top-level version constraint updated:

- "next": "^16.2.6",
+ "next": "^16.2.11",

This ensures future npm install runs cannot accidentally resolve back to a vulnerable 16.2.x version below 16.2.11.

2. Resolved package versions and integrity hashes updated:

 "node_modules/@next/env": {
-  "version": "16.2.7",
-  "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.7.tgz",
-  "integrity": "sha512-tMJizPlj6ZYpBMMdK8S0LJufrP4QTdR6pcv9KQ/bVETPAmg0j1mlHE9G2c38UyGHxoBapgwuj7XjbGJ2RcDFOg=="
+  "version": "16.2.11",
+  "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.11.tgz",
+  "integrity": "sha512-0do5A3BJ2gxWr0ZCMcD6BhW+e595jyxdTl3rXTS6lOtD8ektMiW6CO+EPwt1Eca1DBnm90r/7GdiKWBKxH++DA==",
+  "license": "MIT"
 },

The same pattern repeats for platform-specific SWC compiler packages (@next/swc-darwin-arm64, @next/swc-darwin-x64, and their Linux/Windows equivalents). Each receives:

  • An updated version field (16.2.716.2.11)
  • A new resolved URL pointing to the patched tarball
  • A new integrity hash that cryptographically verifies the correct artifact is downloaded
  • An explicit "license": "MIT" field (a minor metadata improvement in the new release)

Why Updating the Lock File Matters

It is not enough to change only package.json. The package-lock.json contains the exact resolved versions and integrity hashes that npm ci uses in CI/CD pipelines. If only package.json were updated, a npm ci run would fail or — worse — silently install a cached version of 16.2.7 from a local npm cache. Updating both files ensures every environment (developer laptops, CI runners, production build servers) installs 16.2.11.

What Next.js 16.2.11 Actually Fixes

The patch in 16.2.11 corrects the Turbopack route resolution logic so that the middleware invocation step is never skipped, regardless of locale count. The single-locale fast path now correctly passes requests through the middleware pipeline before handing them off to the App Router renderer.


Prevention & Best Practices

1. Pin Dependencies Precisely in Lock Files

Use npm ci (not npm install) in CI/CD pipelines. This command respects the lock file exactly and refuses to install if package.json and package-lock.json are out of sync — preventing silent version drift.

2. Run SCA Scanners as Part of CI

Tools like Trivy, Snyk, and Socket scan your package-lock.json against CVE databases on every pull request. This is exactly how CVE-2026-64642 was detected here — Trivy flagged the vulnerable next@16.2.7 entry before it reached production.

# Example GitHub Actions step
- name: Run Trivy vulnerability scanner
  uses: aquasecurity/trivy-action@master
  with:
    scan-type: 'fs'
    scan-ref: '.'
    severity: 'HIGH,CRITICAL'

3. Do Not Rely Solely on Middleware for Security

The Next.js documentation itself notes that middleware runs in the Edge Runtime and should be treated as a first line of defense, not the only one. For truly sensitive routes, validate the session inside the route handler or server component as well:

// app/dashboard/page.tsx
import { getServerSession } from 'next-auth';
import { redirect } from 'next/navigation';

export default async function DashboardPage() {
  const session = await getServerSession();
  if (!session) {
    redirect('/login'); // defense-in-depth
  }
  // render protected content
}

This defense-in-depth approach means a future middleware bypass — in any framework version — cannot expose sensitive data on its own.

4. Subscribe to Security Advisories

5. Relevant Standards

  • OWASP Top 10 A07:2021 — Identification and Authentication Failures: Middleware bypass is a textbook example of this category
  • CWE-287 — Improper Authentication: The security control (middleware) is present but can be circumvented
  • OWASP ASVS v4.0 Section 4.1: Requires that access control checks are enforced server-side and cannot be bypassed by client manipulation

Key Takeaways

  • Single-locale Turbopack setups are not safe from middleware bypass on next@16.2.7 — this is a specific, reproducible trigger condition, not a theoretical edge case.
  • package-lock.json integrity hashes are a security control: the updated SHA-512 hashes for @next/env-16.2.11 and @next/swc-*-16.2.11 ensure the correct, patched tarballs are installed everywhere.
  • Middleware-only auth is fragile: CVE-2026-64642 demonstrates why server component and API route handlers should independently verify sessions, even when middleware is in place.
  • Trivy caught this before deployment: static dependency scanning on package-lock.json is a low-cost, high-value control that caught a high-severity auth bypass at the PR stage.
  • The ^ semver range in package.json was insufficient protection: ^16.2.6 allowed 16.2.7 (vulnerable) to be installed. Explicitly bumping the lower bound to ^16.2.11 closes the window for future installs.

How Orbis AppSec Detected This

  • Source: The package-lock.json dependency manifest, which records the exact resolved version of next (16.2.7) used across all environments.
  • Sink: The Turbopack route resolver's middleware invocation logic within next@16.2.7, which omits the middleware execution step for App Router requests when a single locale is configured — effectively a no-op security control for matched routes.
  • Missing control: The internal routing pipeline lacked a guard ensuring middleware was always invoked before route rendering, regardless of locale count or build tool selection.
  • CWE: CWE-287 — Improper Authentication (the authentication middleware is present but bypassable due to a routing logic defect).
  • Fix: Updated next from 16.2.7 to 16.2.11 in both package.json and package-lock.json, replacing all affected @next/* package entries and their integrity hashes with the patched versions.

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.


Conclusion

CVE-2026-64642 is a sharp reminder that framework internals — particularly the interaction between build tools, routing engines, and middleware pipelines — can create authentication bypasses that are completely invisible in application code. The middleware.ts file looked correct. The next.config.js looked correct. The vulnerability lived entirely inside the next package itself, triggered by a specific combination of features that many real-world projects use.

The fix is straightforward: upgrade to next@16.2.11. But the broader lesson is architectural — authentication logic should never live in a single layer. Combine middleware-level checks with server-side session validation inside route handlers, keep your dependency scanner running on every PR, and treat your package-lock.json as a security artifact that deserves the same attention as your source code.


References

Frequently Asked Questions

What is a middleware bypass vulnerability in Next.js?

A middleware bypass means an attacker can craft a request that skips the middleware function entirely, so any authentication, authorization, or rate-limiting logic placed there never runs.

How do you prevent middleware bypass in Next.js?

Keep Next.js up to date, avoid relying solely on middleware for security-critical checks, and apply defense-in-depth by also validating sessions inside route handlers and API endpoints.

What CWE is middleware bypass?

CWE-287 (Improper Authentication) — the security control that should verify identity is circumvented before it can execute.

Is upgrading the package enough to prevent this vulnerability?

Yes for CVE-2026-64642 specifically, but as a general principle you should also add server-side session validation inside protected routes so a future bypass cannot expose sensitive data.

Can static analysis detect middleware bypass vulnerabilities?

Scanners like Trivy can flag known-vulnerable package versions. Dynamic analysis and manual code review are also important for detecting logic-level bypass patterns.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #388

Related Articles

critical

How User Enumeration Happens in Django Forms and How to Fix It

A critical user enumeration vulnerability in the volunteers application allowed attackers to systematically discover registered email addresses through distinct error messages in signup and password reset forms. The fix replaces specific error messages with generic ones, preventing information disclosure while maintaining application functionality.

critical

How Authentication Bypass Happens in Node.js WebSocket Services and How to Fix It

The HousePanel push notification service exposed GET and POST endpoints without any authentication checks, allowing unauthenticated attackers to send arbitrary push notifications to connected smart devices. This critical vulnerability was fixed by implementing mandatory token validation on all protected endpoints, ensuring only authenticated requests can trigger push operations.

critical

How Missing API Authentication Happens in Node.js and How to Fix It

The GitHub API integration in `src/github.mjs` was making unauthenticated requests, subjecting the application to GitHub's strict 60 requests/hour rate limit. This fix adds secure authentication token injection from environment variables using conditional header spreading, enabling authenticated requests with a much higher rate limit (5,000 requests/hour).

high

How OAuth 2.0 Authorization Code Interception happens in PHP and how to fix it

The Weibo OAuth login implementation in `trunk/web/login_weibo.php` was missing PKCE (Proof Key for Code Exchange), allowing attackers with network access to exchange intercepted authorization codes for access tokens. The fix adds cryptographic binding between the authorization request and token exchange using SHA256 code challenges.

high

How OAuth Token Binding Prevents Session Hijacking in Weibo Login Implementation

A critical vulnerability in the Weibo OAuth login implementation allowed attackers to replay stolen access tokens across different user sessions. By binding the OAuth access token to the session ID using cryptographic hashing, the fix ensures that intercepted tokens cannot be reused to hijack other sessions, even if compromised via MITM or XSS attacks.

high

How Unauthenticated Endpoint Exposure Happens in Node.js and How to Fix It

A high-severity unauthenticated endpoint exposure was discovered in `dep/src/server/index.js`, where the `/--ziko--` route served internal application state (`globalThis.Ziko`) to any network-connected client without any authentication or environment guard. The fix adds a single production environment check that returns a `404` before the sensitive data is ever sent. This kind of "debug route left in production" vulnerability is surprisingly common in Node.js applications and can silently leak c