Nuxt: Dot segments in the request path bypass `server/middleware` path checks and server route rules on page routes
Impact
Nuxt versions 4.6.0 to 4.6.2 have a vulnerability where dot segments in the request path can bypass server-side controls, allowing an unauthenticated attacker to access restricted pages. The issue is due to a mismatch in path resolution between the page router and server middleware. Affected versions can be exploited by a client that sends the path as written, bypassing browser resolution of dot segments.
Summarized by @cf/meta/llama-3.3-70b-instruct-fp8-fast. Verify details against the original sources.Browsers resolve dot segments before sending a request, so exploitation requires a client that sends the path as written.
Affected packages
Start with the recorded fix for your release branch. Check your installed version and test compatibility before upgrading. Fixing this advisory does not rule out other vulnerabilities in the release.
| Affected range | Recorded fix |
|---|---|
| From 4.6.0 before 4.6.3Semantic versions | 4.6.3 |
Version evidence: OSV · GHSA-9v7c-q64q-vv33
View original version evidence (0 explicit versions)
| Affected range | Recorded fix |
|---|---|
| From 4.6.0 before 4.6.3Semantic versions | 4.6.3 |
Version evidence: OSV · GHSA-9v7c-q64q-vv33
View original version evidence (0 explicit versions)
Affected products
Vendor version evidence. Product records are separate from automatic dependency matching.
nuxt · GitHub_M
nuxt
1 range
nuxt · GitHub_M
nuxt
Compare with this publisher’s ranges. This does not inspect your installation.
affected
>= 4.6.0, < 4.6.3
Other versions: unknown
@nuxt · GitHub_M
nitro-server
1 range
@nuxt · GitHub_M
nitro-server
Compare with this publisher’s ranges. This does not inspect your installation.
affected
>= 4.6.0, < 4.6.3
Other versions: unknown
Original source description
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:
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/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.- Nuxt
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.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):
// 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.
Inside the record
Evidence available
Describes the evidence in this view, not whether the product is safe.
Original records
CVE-2026-119200View the latest unmodified CVE JSON from the official source. It may be newer than this imported page.
cve.new JSON →Underlying weaknesses
The source’s classification of what caused the vulnerability.
Contributing organizations · 1
Assigning organization
What changed
Follow changesLarge field values are marked as truncated previews. Original source snapshots remain retained.