In May 2026, Vercel published a massive, coordinated security release addressing 13 separate advisories across Next.js.
Tucked deep inside the release notes was one line that should make every engineering lead pause
App Router segment-prefetch bypass, incomplete fix follow-up.
Read that phrase again. Vercel didn’t just patch a vulnerability. They patched a patch. A security fix shipped to resolve an authorization bypass failed to close the underlying gap, requiring a second emergency release to clean up what the first one missed.
Alongside it in the same May snapshot were three more advisories carrying the exact same mechanism: an auth bypass via App Router segment-prefetch URLs, a Pages Router i18n default-locale path bypass, and a dynamic route parameter injection flaw. Vercel’s advisory statement was unusually direct
Affects applications that rely on middleware.js or proxy.js for authorization.
Worse, Vercel noted that unlike previous high-severity bugs, they had not deployed platform-level WAF rules for this release because these advisories could not be reliably blocked at the WAF layer. If your application relied on middleware to enforce access controls, platform-level network shields couldn’t save you. You had to patch your application code.
Five distinct authorization bypasses have hit Next.js in fourteen months. They aren’t isolated accidents. They are the predictable output of an architectural mismatch.
Where this started?
Most teams remember when the dam broke.
On March 21, 2025, security researchers disclosed CVE-2025-29927, a CVSS 9.1 critical vulnerability affecting virtually every active production version of Next.js.
The root cause was disarmingly simple. Next.js used an internal header x-middleware-subrequest to prevent infinite loops when middleware invoked sub-requests. The framework trusted this header implicitly. If an incoming HTTP request contained x-middleware-subrequest: true, Next.js assumed middleware had already executed and skipped middleware.js entirely.
Attackers didn’t need a zero-day payload or a buffer overflow. They added a single HTTP header to their request, bypassed every authentication gate living inside middleware, and hit protected backend routes directly.
Vercel protected Vercel-hosted deployments at the platform edge almost immediately, but self-hosted applications running next start with output: "standalone" were left wide open until maintainers manually updated their dependencies.
In their post-mortem analysis of the March 2025 flaw, Datadog Security Labs reached a conclusion that foreshadowed everything to come
Middleware should supplement, not replace, robust security measures placed closer to the data source.
The industry treated CVE-2025-29927 as a one-off header-spoofing bug. They updated their package locks, closed the ticket, and went back to work.
That was a mistake.
What happened next?
Over the next fourteen months, the bypasses kept coming. Each arrived with a new CVE number, a new technical description, and the exact same structural flaw.
Look at the timeline
Pages Router i18n Bypass (CVE-2026-44573)
In Pages Router applications with internationalization (i18n) enabled, middleware evaluated standard request paths but failed to recognize the locale-less data route at /_next/data/<buildId>/<page>.json. A request sent directly to that JSON endpoint bypassed middleware entirely, returning full server-rendered JSON payloads—including whatever sensitive data getServerSideProps fetched—without firing authentication checks.
Dynamic Route Injection (CVE-2026-44574)
Patched in the May 6, 2026 coordinated release. Middleware inspected the visible URL path, a public route like /safe and approved the request. But the App Router resolved the underlying page using internal, injected routing parameters that pointed to a protected route. Middleware evaluated what it saw; the framework rendered what was injected.
App Router Transport Exploits (CVE-2026-44575)
Patched in the same May 2026 window. This flaw exploited internal App Router transport formats, specifically .rsc and segment-prefetch requests. By requesting alternate payload formats directly, attackers bypassed the matching logic configured inside middleware.
July 2026 Security Release
Vercel patched yet another authorization bypass specific to App Router applications compiled with Turbopack containing a single entry in config.i18n.locales.
So, what is the issue?
We should not treat these as five separate bugs. They are five different expressions of a single structural gap
Middleware checks one representation of a request, while the App Router resolves the page using a different, parallel representation.
Middleware evaluates a visible URL, a header string, or a matcher regex pattern. But the App Router is a complex, multi-transport engine handling Server Components, prefetch segments, JSON data routes, and locale rewrites.
Whenever the representation checked by middleware fails to match the representation resolved by the renderer, the check breaks. Patching the matcher doesn’t solve the problem. It just waits for the next transport feature to introduce another mismatch.
Not just a security flaw but a design mismatch
To understand why this gap exists, you have to look at how middleware was engineered.
Middleware in Next.js runs on the Edge Runtime. It executes on every single matched request before the request touches the Node.js server or rendering engine.
Because it sits on the edge and intercepts every incoming request, performing heavy database calls or session lookups inside middleware creates a massive performance penalty. If every static asset, API call, and page navigation has to wait for an edge function to query a database across the network, latency spikes across your entire application.
For years, Next.js tutorials and community guides recommended keeping middleware lightweight. Check if a session cookie exists, verify its signature, and redirect unauthenticated users etc.
Teams took that guidance and made an operational leap. They turned middleware into their primary access control layer. They assumed that if middleware approved the request, downstream Server Components and API routes were safe.
That assumption violated the core constraints of the platform. Middleware was designed as a fast pre-flight filter to speed up user redirection, not an authoritative policy enforcement point. Teams used it as a security guard because it was convenient, ignoring the fact that the framework’s own rendering engine had backdoor paths around it.
Do we have a fix?
Vercel didn’t just ship patches for these CVEs. They overhauled their official documentation to tell developers to stop using middleware as an authorization boundary.
Next.js’s current official security guide explicitly mandates the Data Access Layer (DAL) pattern.
Instead of trusting the routing layer to block unauthorized requests, authentication and authorization checks must sit inside dedicated, server-only modules placed directly next to database calls.
The documentation applies this rule to both reads and mutations
Just as we recommend a Data Access Layer for reading data, you can apply the same pattern to mutations. This keeps authentication, authorization, and database logic in a dedicated server-only module, while
use serveractions stay thin.
Vercel’s current security audit checklist asks point-blank
Is there an established practice for an isolated Data Access Layer? Verify that database packages and environment variables are not imported outside the Data Access Layer.
This marks an acknowledged shift in official framework guidance. Community guides and vendor documentations now carry explicit warnings. Middleware is no longer considered safe for primary authorization.
A useful mental model for this shift comes from security tooling provider WorkOS. Middleware is the bouncer at the front door; the Data Access Layer is the gate agent checking the boarding pass.
The bouncer can be tricked by a fake ID, a back-door entrance, or a bad matcher rule. But even if an attacker tricks the bouncer and slips inside the building, the gate agent stands directly in front of the airplane door. If they don’t have a valid boarding pass attached to that specific seat, they don’t get on the plane.
In code, that means moving from this
// ❌ DANGEROUS: Relying on middleware to protect this component
export default async function AdminDashboard() {
const data = await db.adminStats.findMany(); // Assumes middleware already checked auth
return <AdminView data={data} />;
}To this
// ✅ SECURE: Authoritative check inside the Data Access Layer
import { verifyAdminSession } from ‘@/app/lib/dal’;
export default async function AdminDashboard() {
// DAL function verifies session & permissions directly at execution time
const data = await verifyAdminSession(async () => {
return await db.adminStats.findMany();
});
return <AdminView data={data} />;
}Conclusion
If you configured your Next.js authentication model in 2023 or 2024 by dropping check logic into middleware.ts and assuming your backend routes were secure, your architecture is built on outdated guidance.
Five advisories in fourteen months proved that URL matchers and edge proxy checks cannot guarantee that a request won’t resolve to a protected payload.
Here is your remediation checklist
Audit
middleware.tsimmediately - Treat middleware strictly as an optimization tool for fast redirects and preliminary cookie presence checks. Remove all hard security assumptions from it.Build an isolated Data Access Layer - Wrap every database query, internal API call, and Server Action mutation in dedicated server-only functions (
import 'server-only') that execute explicit permission checks before returning data.Never trust request context - Verify permissions using server-side session tokens retrieved directly inside the Data Access Layer, not passed-down custom headers or route parameters.
Vercel spent fourteen months patching edge bypasses before updating their docs to tell you what security architects knew all along. Never enforce security policies at the routing layer.
Update your code dependencies. But more importantly, update your architecture.





