@NUXT/NITRO-SERVER · GHSA-r99w-jh2x-3mg9 · Package
FIX → 4.6.4
Nuxt 4.6.0 to 4.6.3 renders the page at /admin for a request path like //x/admin, while Nitro route rules and server middleware see the unmatched path. An unauthenticated attacker can skip server-side checks such as auth guards, redirects and security headers on page routes.
first public Nov 2, 2026 · 1 source
Could this affect your app?
Free first check from your website. Connect your repo for the full answer.
Apps built on Nuxt 4.6.0 to 4.6.3 that enforce auth, redirects or headers through server middleware, serverHandlers or route rules keyed on page paths. Nuxt 3.x, 4.0.0 to 4.5.x, and API handlers in server/api and server/routes are not affected per the advisory; appMiddleware and definePageMeta middleware are not affected either.
Not affected if api-only, route-rules-unused, static-export, version-outside-range
Who cares auth-middleware, nitro, nuxt, self-hosted
npm ls @nuxt/nitro-server in the project and check whether the version is 4.6.0 to 4.6.3.serverHandlers with middleware: true, redirect or headers route rules, or server/middleware that check paths like .Since 4.6.0, Nuxt parses a request path that starts with // as a URL with a host before rendering a page, so //x/admin renders the page at /admin. Nitro's routing, Nitro's route rules and server/middleware see the path as //x/admin, so server-side checks keyed on /admin do not apply. The fix for GHSA-9v7c-q64q-vv33 in 4.6.3 covered dot segments but not this form.
An unauthenticated attacker can bypass server-side controls that match on the request path of a page route.
A route-scoped server handler is skipped:
// nuxt.config.ts
export default defineNuxtConfig({
serverHandlers: [{ : , : , : }],
})
Check it with your coding agent
It reads this page and tells you if your code is affected.
Are you affected?
Ask from here. InfraStack checks the affected versions against your stack and answers in your inbox.
InfraStack checks the affected versions against your stack and answers in Slack, with the evidence and the fix.
/adminUpgrade to 4.6.4
@nuxt/nitro-server 4.6.4 (nuxt 4.6.4 depends on it)// in a server middleware, or strip repeated slashes at a reverse proxy or CDN.// server/admin-guard.ts
export default defineEventHandler((event) => {
if (!isAuthenticated(event)) {
throw createError({ statusCode: 401 })
}
})
With this handler, /admin returns 401, but //x/admin and ///x/admin render app/pages/admin.vue along with the data it fetches during server rendering. server/middleware that checks event.path.startsWith('/admin') is skipped in the same way.
Server-side redirect and headers route rules are also skipped, so '/admin/**': { redirect: '/login' } does not redirect //x/admin/secret, and per-route security headers such as Content-Security-Policy are not sent.
Browsers send a path such as //x/admin as written, so a plain link is enough to reach the page.
Not affected:
server/api and server/routes, which Nitro does not match for these paths.appMiddleware route rules and middleware declared with definePageMeta, which are matched against the resolved route.3.x and 4.0.0 to 4.5.x, which pass the path to the page router unchanged, so these requests 404.Fixed in @nuxt/nitro-server@4.6.4, which nuxt@4.6.4 depends on. The renderer now uses the request path exactly as Nitro matched it, so a path starting with // no longer resolves to a different page.
Reject request paths that start with // in a server middleware:
// server/middleware/double-slash.ts
export default defineEventHandler((event) => {
if (event.path.startsWith('//')) {
throw createError({ statusCode: 404 })
}
})
A reverse proxy or CDN that merges repeated slashes before forwarding the request also removes the mismatch.
Thanks to @kq5y for reporting this issue.