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:
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):
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.
This PR contains the following updates:
| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [nuxt](https://nuxt.com) ([source](https://github.com/nuxt/nuxt/tree/HEAD/packages/nuxt)) | [`4.6.2` → `4.6.3`](https://renovatebot.com/diffs/npm/nuxt/4.6.2/4.6.3) |  |  |
---
### Nuxt: Dot segments in the request path bypass `server/middleware` path checks and server route rules on page routes
[CVE-2026-119200](https://nvd.nist.gov/vuln/detail/CVE-2026-119200) / [GHSA-9v7c-q64q-vv33](https://github.com/advisories/GHSA-9v7c-q64q-vv33)
<details>
<summary>More information</summary>
#### 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 `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.
#### Severity
- CVSS Score: 6.5 / 10 (Medium)
- Vector String: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N`
#### References
- [https://github.com/nuxt/nuxt/security/advisories/GHSA-9v7c-q64q-vv33](https://github.com/nuxt/nuxt/security/advisories/GHSA-9v7c-q64q-vv33)
- [https://nvd.nist.gov/vuln/detail/CVE-2026-119200](https://nvd.nist.gov/vuln/detail/CVE-2026-119200)
- [https://github.com/nuxt/nuxt/commit/45463f8b58487e387149ebfb704d6a0834b3a450](https://github.com/nuxt/nuxt/commit/45463f8b58487e387149ebfb704d6a0834b3a450)
- [https://github.com/nuxt/nuxt](https://github.com/nuxt/nuxt)
- [https://github.com/nuxt/nuxt/releases/tag/v4.6.3](https://github.com/nuxt/nuxt/releases/tag/v4.6.3)
This data is provided by [OSV](https://osv.dev/vulnerability/GHSA-9v7c-q64q-vv33) and the [GitHub Advisory Database](https://github.com/github/advisory-database) ([CC-BY 4.0](https://github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>
---
### Release Notes
<details>
<summary>nuxt/nuxt (nuxt)</summary>
### [`v4.6.3`](https://github.com/nuxt/nuxt/releases/tag/v4.6.3)
[Compare Source](https://github.com/nuxt/nuxt/compare/v4.6.2...v4.6.3)
> v4.6.3 is the next patch release.
#### 👉 Changelog
[compare changes](https://github.com/nuxt/nuxt/compare/v4.6.2...v4.6.3)
##### 🚨 Security fixes
- **vite:** do not read files named in client error reports ([`63299e13c`](https://github.com/nuxt/nuxt/commit/63299e13c)) - [GHSA-x287-wcfc-q46c](https://github.com/nuxt/nuxt/security/advisories/GHSA-x287-wcfc-q46c)
- **vite:** deny dev server access to nitro dev output ([`c7e204ec6`](https://github.com/nuxt/nuxt/commit/c7e204ec6)) - [GHSA-648h-gw55-m2g7](https://github.com/nuxt/nuxt/security/advisories/GHSA-648h-gw55-m2g7)
- **vite:** deny serving generated app secret in dev ([`16dfdc2a9`](https://github.com/nuxt/nuxt/commit/16dfdc2a9)) - [GHSA-3xf4-9g3c-4h4w](https://github.com/nuxt/nuxt/security/advisories/GHSA-3xf4-9g3c-4h4w)
- **nitro,nuxt:** handle dot segments in request paths ([`440250d97`](https://github.com/nuxt/nuxt/commit/440250d97)) - [GHSA-9v7c-q64q-vv33](https://github.com/nuxt/nuxt/security/advisories/GHSA-9v7c-q64q-vv33)
- **nuxt:** apply redirect route rules to page islands ([`b20372dbe`](https://github.com/nuxt/nuxt/commit/b20372dbe)) - [GHSA-2fxj-c3j7-rr69](https://github.com/nuxt/nuxt/security/advisories/GHSA-2fxj-c3j7-rr69)
##### 🔥 Performance
- **vite:** skip compiling plain style blocks in the server build ([#​36711](https://github.com/nuxt/nuxt/issues/36711))
- **nitro,nuxt,rspack,webpack:** bundle esm vue + reuse caches ([#​36710](https://github.com/nuxt/nuxt/issues/36710))
- **vite:** avoid quadratic nested dir check for `fs.allow` ([#​36702](https://github.com/nuxt/nuxt/issues/36702))
- **nuxt:** server render internal custom links without RouterLink ([#​36707](https://github.com/nuxt/nuxt/issues/36707))
- **nuxt:** skip unneeded typed routes generation ([#​36645](https://github.com/nuxt/nuxt/issues/36645))
##### 🩹 Fixes
- **nitro:** don't share prerender hints with self-fetched requests ([#​36705](https://github.com/nuxt/nuxt/issues/36705))
- **nuxt:** defer app scope cleanup on external navigation ([#​36713](https://github.com/nuxt/nuxt/issues/36713))
- **nuxt:** prevent useCookie CookieStore sync from rewriting with refresh ([#​36673](https://github.com/nuxt/nuxt/issues/36673))
- **nuxt:** only return redirects from `navigateTo` while middleware runs ([#​36650](https://github.com/nuxt/nuxt/issues/36650))
- **nuxt:** remove purged entries from `_asyncData` ([#​36709](https://github.com/nuxt/nuxt/issues/36709))
- **vite:** skip quoted `import.meta` keys + limit replace to client dev ([#​36703](https://github.com/nuxt/nuxt/issues/36703))
- **nuxt:** hide RouteLocationRaw from navigateTo's public return type ([#​36691](https://github.com/nuxt/nuxt/issues/36691))
- **nuxt:** tree-shake auto-imported `#app` composables ([#​36696](https://github.com/nuxt/nuxt/issues/36696))
- **nuxt:** don't treat constrained route rules as covering dynamic pages ([#​36701](https://github.com/nuxt/nuxt/issues/36701))
- **nuxt:** include `shared/` in build cache hash ([#​36704](https://github.com/nuxt/nuxt/issues/36704))
- **nuxt:** hash keyed function ids + page import names relative to `rootDir` ([#​36697](https://github.com/nuxt/nuxt/issues/36697))
- **nuxt:** encode page paths before matching route rule keys ([#​36683](https://github.com/nuxt/nuxt/issues/36683))
- **nuxt:** handle rejected `updateCallbackDone` of aborted view transition ([#​36639](https://github.com/nuxt/nuxt/issues/36639))
- **ui-templates:** keep loading shader proportions on narrow screens ([#​36654](https://github.com/nuxt/nuxt/issues/36654))
- **nuxt:** reject case-dependent route rule constraints w/ `sensitive: false` ([#​36708](https://github.com/nuxt/nuxt/issues/36708))
- **nuxt:** don't case-fold regex constraints in route rule keys ([#​36694](https://github.com/nuxt/nuxt/issues/36694))
- **nuxt:** normalise page prefix when finding route rule exceptions ([#​36685](https://github.com/nuxt/nuxt/issues/36685))
- **vite:** mirror ssr invalidations for created and deleted files ([`634cba64c`](https://github.com/nuxt/nuxt/commit/634cba64c))
- **nitro:** keep `noScripts` wildcard patterns single-segment ([`fa323db7d`](https://github.com/nuxt/nuxt/commit/fa323db7d))
- **deps:** update unrouting to v0.3.1 ([#​36663](https://github.com/nuxt/nuxt/issues/36663))
- **nuxt:** avoid self-referencing `nuxt/schema` augmentation ([#​36633](https://github.com/nuxt/nuxt/issues/36633))
- **nuxt:** let nightly runtime resolve its own `nuxt/*` imports ([#​36632](https://github.com/nuxt/nuxt/issues/36632))
- **nuxt:** don't warn for vite+ `vite.config` files ([#​36628](https://github.com/nuxt/nuxt/issues/36628))
- **kit:** keep generated declaration first in tsconfig `include` ([#​36627](https://github.com/nuxt/nuxt/issues/36627))
- **nuxt:** clamp numeric `v-for` sources in island renders at render time ([#​36623](https://github.com/nuxt/nuxt/issues/36623))
- **rspack,webpack:** register vue-loader plugin only once per config ([#​36622](https://github.com/nuxt/nuxt/issues/36622))
- **nitro:** abort the portable request when the client disconnects ([#​36652](https://github.com/nuxt/nuxt/issues/36652))
- **deps:** update nitropack to 2.13.5 + drop obsolete workarounds ([#​36649](https://github.com/nuxt/nuxt/issues/36649))
##### 📖 Documentation
- note provide/inject limit in server components ([#​35837](https://github.com/nuxt/nuxt/issues/35837))
- use American spelling in a few guides ([#​36706](https://github.com/nuxt/nuxt/issues/36706))
- document controlling prefetch hints via `build:manifest` hook ([#​36695](https://github.com/nuxt/nuxt/issues/36695))
- update StackBlitz link to point to version 4 ([#​36674](https://github.com/nuxt/nuxt/issues/36674))
- link to the 2.x docs ([#​36640](https://github.com/nuxt/nuxt/issues/36640))
- clarify that island props must be validated before iteration ([`4b12d15c9`](https://github.com/nuxt/nuxt/commit/4b12d15c9))
##### ✅ Tests
- list `NUXT_B4023` as main-only ([`4fd54ff9a`](https://github.com/nuxt/nuxt/commit/4fd54ff9a))
- wait for leave transition before each scroll behaviour test ([`453406999`](https://github.com/nuxt/nuxt/commit/453406999))
- **vite:** assert spa server bundle does not ship the app ([#​36699](https://github.com/nuxt/nuxt/issues/36699))
- **nuxt:** cover route rule coverage under a base url ([#​36682](https://github.com/nuxt/nuxt/issues/36682))
- list `NUXT_B9006` as main-only ([`e107e0f40`](https://github.com/nuxt/nuxt/commit/e107e0f40))
##### 🤖 CI
- only run full checks for the last merge queue entry ([`132698a46`](https://github.com/nuxt/nuxt/commit/132698a46))
- run a reduced matrix in the merge queue ([`7d228ba4b`](https://github.com/nuxt/nuxt/commit/7d228ba4b))
- compare merge queue changes against the base branch ([`bad8c3637`](https://github.com/nuxt/nuxt/commit/bad8c3637))
- notify resolved issues after publishing a release ([`9d47884f3`](https://github.com/nuxt/nuxt/commit/9d47884f3))
- remove broken ai-moderator and ecosystem-ci trigger workflows ([`1d89ad434`](https://github.com/nuxt/nuxt/commit/1d89ad434))
##### 🎉 New Contributors
- rynx.z ([@​rynx-cc](https://github.com/rynx-cc))
- Felix Fang ([@​FelixFangX](https://github.com/FelixFangX))
- Volkan Akyel ([@​volkanakyel](https://github.com/volkanakyel))
- Gareth ([@​0xgdr](https://github.com/0xgdr))
##### ❤️ Contributors
- Daniel Roe ([@​danielroe](https://github.com/danielroe))
- rynx.z ([@​rynx-cc](https://github.com/rynx-cc))
- Felix Fang ([@​FelixFangX](https://github.com/FelixFangX))
- Max ([@​onmax](https://github.com/onmax))
- Volkan Akyel ([@​volkanakyel](https://github.com/volkanakyel))
- Bochkarev Ivan ([@​Ibochkarev](https://github.com/Ibochkarev))
- Gareth ([@​0xgdr](https://github.com/0xgdr))
- Hugo ([@​HugoRCD](https://github.com/HugoRCD))
- Sébastien Chopin ([@​atinux](https://github.com/atinux))
- Eduardo San Martin Morote ([@​posva](https://github.com/posva))
- Baptiste Leproux ([@​larbish](https://github.com/larbish))
- Benjamin Canac ([@​benjamincanac](https://github.com/benjamincanac))
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Enabled.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xODEuOSIsInVwZGF0ZWRJblZlciI6IjQ0LjE4MS45IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
renovate
scheduled this pull request to auto merge when all checks succeed 2026-10-31 01:09:28 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
This PR contains the following updates:
4.6.2→4.6.3Nuxt: Dot segments in the request path bypass
server/middlewarepath checks and server route rules on page routesCVE-2026-119200 / GHSA-9v7c-q64q-vv33
More information
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 andserver/middlewaresee the path with those segments still in place. A request for/%2e/admintherefore renders the page at/admin, while server-side checks keyed on/admindo not apply.Impact
An unauthenticated attacker can bypass server-side controls that match on the request path of a page route.
server/middlewarethat checksevent.path(orevent.node.req.url) is skipped:With this middleware,
/adminreturns 401, but/%2e/admin,/.%2e/adminand/x/%2e%2e/adminreach the middleware withevent.pathset to/./admin,/../adminand/x/../admin, and renderapp/pages/admin.vuealong with the data it fetches during server rendering.Server-side
redirectandheadersroute rules are skipped in the same way, so'/admin/**': { redirect: '/login' }does not redirect/%2e/admin/secret, and per-route security headers such asContent-Security-Policyare not sent.Not affected:
server/apiandserver/routes. Nitro's router does not resolve dot segments, so these requests do not reach the handler.appMiddlewareroute rules and middleware declared withdefinePageMeta, which are matched against the resolved route.3.xand4.0.0to4.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.3and@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):
Checking
getRequestURL(event).pathnameinstead ofevent.pathis not a sufficient workaround: it resolves dot segments, but keeps percent-encoding such as%61that the page router decodes. Path checks in server middleware should also account for the page router matching paths case-insensitively unlessrouter.options.sensitiveis 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.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Release Notes
nuxt/nuxt (nuxt)
v4.6.3Compare Source
👉 Changelog
compare changes
🚨 Security fixes
63299e13c) - GHSA-x287-wcfc-q46cc7e204ec6) - GHSA-648h-gw55-m2g716dfdc2a9) - GHSA-3xf4-9g3c-4h4w440250d97) - GHSA-9v7c-q64q-vv33b20372dbe) - GHSA-2fxj-c3j7-rr69🔥 Performance
fs.allow(#36702)🩹 Fixes
navigateTowhile middleware runs (#36650)_asyncData(#36709)import.metakeys + limit replace to client dev (#36703)#appcomposables (#36696)shared/in build cache hash (#36704)rootDir(#36697)updateCallbackDoneof aborted view transition (#36639)sensitive: false(#36708)634cba64c)noScriptswildcard patterns single-segment (fa323db7d)nuxt/schemaaugmentation (#36633)nuxt/*imports (#36632)vite.configfiles (#36628)include(#36627)v-forsources in island renders at render time (#36623)📖 Documentation
build:manifesthook (#36695)4b12d15c9)✅ Tests
NUXT_B4023as main-only (4fd54ff9a)453406999)NUXT_B9006as main-only (e107e0f40)🤖 CI
132698a46)7d228ba4b)bad8c3637)9d47884f3)1d89ad434)🎉 New Contributors
❤️ Contributors
Configuration
📅 Schedule: (UTC)
🚦 Automerge: Enabled.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR has been generated by Mend Renovate CLI.
8898b91932to14263084a5