GHSA-9v7c-q64q-vv33

    Dashboard / Vulnerabilities / GHSA-9v7c-q64q-vv33

    GHSA-9v7c-q64q-vv33

    Published: 30 Oct 2026Last Modified: 30 Oct 2026

    Summary: Nuxt: Dot segments in the request path bypass `server/middleware` path checks and server route rules on page routes

    Details: ### 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 `[email protected]` and `@nuxt/[email protected]`. 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.

    Affected packages

    Package

    Name: nuxt

    Purl: pkg:npm/nuxt

    Affected ranges

    Type: SEMVER

    Events:

    Introduced- 4.6.0
    Fixed -4.6.3

    Affected versions

    Common Vulnerability Scoring System

    Attack Vector
    Network
    Adjacent
    Local
    Physical
    Privileges Required
    None
    Low
    High
    User Interaction
    None
    Required
    Scope
    Unchanged
    Changed
    Confidentiality
    None
    Low
    High
    Integrity
    None
    Low
    High
    Availability
    None
    Low
    High
    GHSA-9v7c-q64q-vv33 | CVE-DB