CVE-2025-29927: the Next.js middleware bypass
In March 2025, Next.js published a critical vulnerability: a request carrying a specific internal header, x-middleware-subrequest, made Next.js skip the middleware entirely. Apps that checked logins in middleware let anyone through.
Who was affected
The header was meant for Next.js's own internal requests, to stop middleware from calling itself in a loop. Nothing stopped a request from outside from sending it. Affected were apps that:
- used middleware for authorization (redirect to login, block paths), and
- ran self-hosted —
next startor thestandaloneoutput, which is how Dokploy, Coolify and most Docker setups run Next.js — on an affected version.
Deployments on Vercel and Netlify were not affected: their platforms handle middleware differently. That is the uncomfortable lesson — the same app was safe on a managed platform and open on your own server.
The fix
Update to 15.2.3, 14.2.25, 13.5.9 or 12.3.5 (or later in each line). Until then, a reverse proxy can strip or reject the x-middleware-subrequest header. And independently of this bug: middleware is a good first check, not the only one — check authorization again where the data is read.
What it means for self-hosting
Self-hosting moves a part of security from the platform to you:
- Advisories that only hit self-hosted setups need to reach you, with the information that you are the affected kind of deployment.
- The lockfile is the truth, not
package.json: a range like^15.1.0says nothing about what is installed. - Framework packages move together.
nextand its@next/*packages updated to different versions break builds; update them as one.
How Moatline does it
Moatline reads the exact versions from the lockfile of every repository, checks them against the advisory database npm itself uses, and opens a pull request with the smallest fix — next and @next/* moved together, checked by your CI. Merged, it deploys through your platform and watches the live site, rolling back if the deploy breaks it. See how it works.