GHSA-9v7c-q64q-vv33: Nuxt: Dot segments in the request path bypass `server/middleware` path checks and server route rules on page routes
Summary
Since 4.6.0, Nuxt resolves . and .. segments in the request path, including percent-encoded forms such as %2e, before rendering a page. Nitro's routing, Nitro's route rules and server/middleware see the path with those segments still in place. A request for /%2e/admin therefore renders the page at /admin, while server-side checks keyed on /admin do not apply.
Impact
An unauthenticated attacker can bypass server-side controls that match on the request path of a page route.
server/middleware that checks event.path (or event.node.req.url) is skipped:
ts export default defineEventHandler((event) => { if (event.path.startsWith('/admin') && !isAuthenticated(event)) { throw createError({ statusCode: 401 }) } })
With this middleware, /admin returns 401, but /%2e/admin, /.%2e/admin and /x/%2e%2e/admin reach the middleware with event.path set to /./admin, /../admin and /x/../admin, and render app/pages/admin.vue along with the data it fetches during server rendering.
Server-side redirect and headers route rules are skipped in the same way, so '/admin/': { redirect: '/login' } does not redirect /%2e/admin/secret, and per-route security headers such as Content-Security-Policy are not sent.
Not affected:
- API handlers in server/api and server/routes. Nitro's router does not resolve dot segments, so these requests do not reach the handler. - appMiddleware route rules and middleware declared with definePageMeta, which are matched against the resolved route. - Nuxt 3.x and 4.0.0 to 4.5.x, which pass the path to the page router unchanged, so these requests 404.
Browsers resolve dot segments before sending a request, so exploitation requires a client that sends the path as written.
Patches
Fixed in nuxt@4.6.3 and @nuxt/nitro-server@4.6.3. A page request whose path contains . or .. segments now receives a 404 instead of rendering the page the path resolves to, and route-rule keys and lookup paths have their dot segments resolved, including percent-encoded spellings, before they are compared.
Workarounds
Reject dot segments in a server middleware that runs before your other middleware (middleware runs in file name order):
ts // server/middleware/0.dot-segments.ts export default defineEventHandler((event) => { if (/(?:^|\/)\.{1,2}(?:\/|$)/.test(event.path.split('?')[0])) { throw createError({ statusCode: 404 }) } })
Checking getRequestURL(event).pathname instead of event.path is not a sufficient workaround: it resolves dot segments, but keeps percent-encoding such as %61 that the page router decodes. Path checks in server middleware should also account for the page router matching paths case-insensitively unless router.options.sensitive is set.
A reverse proxy or CDN that normalises the request path before forwarding it also removes the mismatch.
Credits
Thanks to @vinzabe, @nikhilagrawalsf (Nikhil Agrawal, Mettle Labs), @0xjunwei and @kq5y, who reported this issue independently.
Other sources
Nuxt is an open-source web development framework for Vue.js. From 4.6.0 until 4.6.3, Nuxt resolves literal or percent-encoded dot segments before rendering a page while Nitro routing, server/middleware checks, and server route rules evaluate the unresolved path. A request such as /%2e/admin can therefore render app/pages/admin.vue and its server-rendered data while checks keyed to /admin, redirects, or per-route security headers do not apply. API handlers, appMiddleware, Nuxt 3, and Nuxt 4.0.0 through 4.5.x are not affected, and exploitation requires a client that sends dot segments without browser normalization. This issue is fixed in version 4.6.3.
— OSV
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/@nuxt/nitro-serverto a version that resolves this vulnerability.Fixed in 4.6.3 - Upgrade
Upgrade
npm/nuxtto a version that resolves this vulnerability.Fixed in 4.6.3 - Upgrade
Upgrade
nuxtto a version that resolves this vulnerability.Fixed in 4.6.3 - Upgrade
Upgrade
@nuxt/nitro-serverto a version that resolves this vulnerability.Fixed in 4.6.3 - Compensating control
Add an early server middleware, such as server/middleware/0.dot-segments.ts, that rejects request paths containing literal or percent-encoded `.` or `..` segments with a 404 before other middleware runs.