---
id: CVE-2026-119200
aliases:
  - GHSA-9v7c-q64q-vv33
title: >-
  Nuxt: Dot segments in the request path bypass `server/middleware` path checks
  and server route rules on page routes
summary: >-
  Nuxt: Dot segments in the request path bypass `server/middleware` path checks
  and server route rules on page routes
severity: medium
cvss: 6.5
cwe:
  - CWE-41
  - CWE-436
  - CWE-863
vendor: nuxt
product: nuxt
ecosystem: npm
affected:
  - 'nuxt >= 4.6.0, < 4.6.3'
  - '@nuxt/nitro-server >= 4.6.0, < 4.6.3'
patched:
  - nuxt 4.6.3
  - '@nuxt/nitro-server 4.6.3'
published: '2026-10-30'
updated: '2026-10-30'
sourceUpdated: '2026-10-30T23:00:54Z'
source: GHSA
sourceUrl: 'https://github.com/advisories/GHSA-9v7c-q64q-vv33'
references:
  - url: 'https://github.com/nuxt/nuxt/security/advisories/GHSA-9v7c-q64q-vv33'
  - url: 'https://nvd.nist.gov/vuln/detail/CVE-2026-119200'
  - url: >-
      https://github.com/nuxt/nuxt/commit/45463f8b58487e387149ebfb704d6a0834b3a450
  - url: 'https://github.com/nuxt/nuxt/releases/tag/v4.6.3'
  - url: 'https://github.com/advisories/GHSA-9v7c-q64q-vv33'
tags:
  - ghsa
  - npm
epss: 0.00339
epssPercentile: 0.27331
ingestedAt: '2026-10-30T23:11:25.778Z'
---

## Overview

### 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.

## Affected packages

- `nuxt >= 4.6.0, < 4.6.3`
- `@nuxt/nitro-server >= 4.6.0, < 4.6.3`

## Remediation

Upgrade to a patched release:

- `nuxt 4.6.3`
- `@nuxt/nitro-server 4.6.3`
