Originally created by: renovate[bot]
Originally owned by: luifr10
This PR contains the following updates:
Nuxt: Reflected XSS in navigateTo() external redirect
CVE-2026-45669 / GHSA-fx6j-w5w5-h468
More information
#### Details
##### Summary
`navigateTo()` with `external: true` generates a server-side HTML redirect body containing a `<meta http-equiv="refresh">` tag. The destination URL is only sanitized by replacing `"` with `%22`, leaving `<`, `>`, `&`, and `'` unencoded. An attacker who can influence the URL passed to `navigateTo(url, { external: true })` can break out of the `content="…"` attribute and inject arbitrary HTML/JavaScript that executes under the application's origin.
This is a different root cause from CVE-2024-34343 (GHSA-vf6r-87q4-2vjf), which addressed `javascript:` protocol bypass. The issue here is triggered by any valid URL containing `>`.
##### Impact
Applications that pass user-controlled input to `navigateTo(url, { external: true })` — typically via a `?next=` / `?redirect=` query parameter used for post-login or "return to" flows — are vulnerable to reflected cross-site scripting. The injected script runs in the context of the application's origin during the server-rendered redirect response, before the meta-refresh fires.
##### Details
In `packages/nuxt/src/app/composables/router.ts`, the SSR redirect path builds an HTML response body with only `"` percent-encoded in the destination URL:
:::ts
const encodedLoc = location.replace(/"/g, '%22')
nuxtApp.ssrContext!['~renderResponse'] = {
status: sanitizeStatusCode(options?.redirectCode || 302, 302),
body: `<meta http-equiv="refresh" content="0; url=${encodedLoc}">`,
headers: { location: encodeURL(location, isExternalHost) },
}
The `Location` header is normalised through `encodeURL()` (which uses the `URL` constructor and correctly percent-encodes attribute-significant characters). The HTML body uses a narrower sanitiser. That mismatch is the root cause.
##### Proof of concept
Global middleware that forwards a query parameter to `navigateTo`:
:::ts
// middleware/redirect.global.ts
export default defineNuxtRouteMiddleware((to) => {
const next = to.query.next as string | undefined
if (next) {
return navigateTo(next, { external: true })
}
})
Request:
GET /?next=https://evil.example/x>
Response body:
:::html
<meta http-equiv="refresh" content="0; url=https://evil.example/x><img src=x onerror=alert(document.domain)>">
The `>` after `evil.example/x` terminates the `content="…"` attribute, and the `
` tag executes JavaScript in the application's origin before any redirect
occurs.
##### Patches
Fixed in `nuxt@4.4.6` and `nuxt@3.21.6` by [#35052](https://redirect.github.com/nuxt/nuxt/pull/35052). The fix percent-encodes the full set of HTML-attribute-significant characters (`&`, `"`, `'`, `<`, `>`) before interpolating the URL into the meta-refresh body
##### Workarounds
If you can't upgrade immediately, validate user-controlled URLs before passing them to `navigateTo(url, { external: true })`. At minimum, normalise through `new URL(input).toString()` and reject inputs containing `<` or `>` (a normalised URL with these characters is malformed and safe to refuse).
#### Severity
- CVSS Score: 5.3 / 10 (Medium)
- Vector String: `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:L/VI:L/VA:N/SC:L/SI:L/SA:N`
#### References
- [https://github.com/nuxt/nuxt/security/advisories/GHSA-fx6j-w5w5-h468](https://redirect.github.com/nuxt/nuxt/security/advisories/GHSA-fx6j-w5w5-h468)
- [https://github.com/nuxt/nuxt/pull/35052](https://redirect.github.com/nuxt/nuxt/pull/35052)
- [https://nvd.nist.gov/vuln/detail/CVE-2026-45669](https://nvd.nist.gov/vuln/detail/CVE-2026-45669)
- [https://github.com/advisories/GHSA-fx6j-w5w5-h468](https://redirect.github.com/advisories/GHSA-fx6j-w5w5-h468)
This data is provided by the [GitHub Advisory Database](https://redirect.github.com/advisories/GHSA-fx6j-w5w5-h468) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
Nuxt: __nuxt_island endpoint does not bind responses to request props, enabling shared-cache poisoning
CVE-2026-46342 / GHSA-g8wj-3cr3-6w7v
More information
#### Details
##### Summary
The `/__nuxt_island/*` endpoint accepts attacker-controlled `props` query/body parameters and renders any island component without verifying that the URL-resident hash (`<name>_<hashid>.json`) was actually issued for those inputs by `<nuxtisland>`. The hash is computed and embedded client-side but never validated server-side, so the same path can return materially different responses depending on the query.
Island components are documented as rendering independently of route context - page middleware does not apply to them, and they are intentionally cacheable as a function of their props. This advisory does **not** treat that contract as a vulnerability. It treats the absence of a binding between the URL the cache keys on and the response served at that URL as one.
##### Impact
In applications where a CDN or reverse-proxy in front of the app caches `/__nuxt_island/*` keyed by path only (ignoring query) - a documented misconfiguration class, see GHSA-jvhm-gjrh-3h93 - an attacker can prime the cache for a path with their own choice of props, and subsequent users requesting the same path receive the attacker's rendered HTML rather than the response intended for them. The cache entry persists until normal expiry.
Where the affected island has any prop flowing into an unsafe HTML sink in application code (`v-html`, `innerHTML`, a third-party renderer treating a prop as HTML), this becomes stored XSS in the embedding page's origin until the cache entry expires. `HttpOnly` cookies remain out of reach but anything else in the origin (other cookies, in-origin requests, DOM state) is reachable by the injected script.
Preconditions:
- `experimental.componentIslands` enabled (or the default `'auto'` with at least one server / island component in the app).
- A shared intermediary cache (CDN, reverse-proxy, edge cache) keyed on path only.
- For the XSS pivot specifically: an application-authored island that puts a prop through an unsafe HTML sink.
Without the second precondition, the response shape is per-request and unaffected. Without the third, the worst case is content-swap / inert HTML injection rather than script execution.
##### Patches
Patched in `nuxt@4.4.6` and `nuxt@3.21.6` by [#35077](https://redirect.github.com/nuxt/nuxt/pull/35077). The island handler now recomputes the expected `hashId` from `(name, props, context)` using the same `ohash` function `<nuxtisland>` already uses to embed the hash in the URL, and rejects requests (HTTP 400) whose URL-resident hash does not match. The response is now a pure function of the request path: a path-keyed shared cache returns the correct response to every requester for that path, and an attacker cannot synthesise a path whose hash matches arbitrary props.
##### Workarounds
For users unable to upgrade immediately:
- Ensure any intermediary cache keys `/__nuxt_island/*` on the full query string, not on the path alone. This is the recommended configuration regardless.
- Audit application-authored islands for props flowing into `v-html` / `innerHTML` / similar HTML sinks; treat island props as untrusted user input.
##### Note on island authentication
> [!IMPORTANT]
> It's important to remember that route middleware does not run when rendering island components, and islands cannot rely on routing-layer auth. Applications gating sensitive data behind page middleware should enforce that auth inside the island's own data layer (server-only routes, `useRequestEvent` + manual session checks, etc.) rather than relying on the embedding page's middleware - this was true before this advisory and remains true after it.
A separate advisory addresses `*.server.vue` *pages* registered as `page_<routename>` islands, where the documented "middleware doesn't run for islands" contract collides with the page's own `definePageMeta({ middleware })` declaration in a way that constitutes a genuine bug rather than documented behaviour.
#### Severity
- CVSS Score: 2.3 / 10 (Low)
- Vector String: `CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:L/VA:N/SC:L/SI:L/SA:N`
#### References
- [https://github.com/nuxt/nuxt/security/advisories/GHSA-g8wj-3cr3-6w7v](https://redirect.github.com/nuxt/nuxt/security/advisories/GHSA-g8wj-3cr3-6w7v)
- [https://github.com/nuxt/nuxt/pull/35077](https://redirect.github.com/nuxt/nuxt/pull/35077)
- [https://nvd.nist.gov/vuln/detail/CVE-2026-46342](https://nvd.nist.gov/vuln/detail/CVE-2026-46342)
- [https://github.com/advisories/GHSA-g8wj-3cr3-6w7v](https://redirect.github.com/advisories/GHSA-g8wj-3cr3-6w7v)
This data is provided by the [GitHub Advisory Database](https://redirect.github.com/advisories/GHSA-g8wj-3cr3-6w7v) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</routename></nuxtisland></nuxtisland></hashid></name>
Nuxt's route middleware is not enforced when rendering .server.vue pages via /__nuxt_island/page_*
CVE-2026-47200 / GHSA-hg3f-28rg-4jxj
More information
#### Details
##### Summary
When `experimental.componentIslands` is enabled (default in Nuxt 4), any `.server.vue` file under `pages/` is automatically registered as a server island under the key `page_<routename>` and exposed via the `/__nuxt_island/:name` endpoint. Until this fix, requests through that endpoint rendered the page component directly via the SSR renderer without instantiating Vue Router, which meant route middleware declared on the page (including `definePageMeta({ middleware })`) did not run.
For Nuxt applications that gate a `.server.vue` *page* behind route middleware as their sole auth check, an unauthenticated attacker could bypass that check by requesting `/__nuxt_island/page_<routename>_<anyhash>` directly and receiving the server-rendered HTML.
##### Affected configurations
All three conditions must hold for an application to be vulnerable:
1. `experimental.componentIslands` is enabled (the default in Nuxt 4; opt-in in Nuxt 3).
2. The application defines one or more `.server.vue` files under `pages/`, registering them as routed pages.
3. Authentication / authorization for at least one such page is enforced solely via route middleware (`middleware/*.ts` referenced from `definePageMeta`), without a server-side check inside the page or its data layer.
Applications that enforce auth inside the island's own data layer (server-only API routes, `useRequestEvent` + manual session checks, etc.) were not affected. The general "route middleware does not run for non-page island *components*" behaviour is documented and unchanged; this advisory concerns the `.server.vue` *page* case specifically, where running middleware is the user's clear expectation.
##### Details
- Build (`packages/nuxt/src/components/templates.ts`): `.server.vue` pages are registered as island components with `page_` prefix, making them addressable through `/__nuxt_island/page_<routename>_<hashid>`.
- Runtime (`packages/nitro-server/src/runtime/handlers/island.ts`): the handler resolves the requested island component and renders it via `renderer.renderToString(ssrContext)`. The Vue Router plugin previously short-circuited middleware execution whenever `ssrContext.islandContext` was set.
- The two paths interact so that route middleware declared on the source page never runs.
##### Proof of concept
Given a page `app/pages/secret.server.vue`:
:::vue
<script setup="" lang="ts">
definePageMeta({ middleware: 'auth' })
</script>
<template>
SECRET DATA
</template>
with `middleware/auth.ts` blocking unauthenticated access:
:::bash
##### Direct page request: blocked by middleware
curl -i http://localhost:3000/secret
##### -> 403 / redirect, depending on the middleware
##### Island request: middleware did not run before this fix
curl -i 'http://localhost:3000/__nuxt_island/page_secret_anyhash'
##### -> 200 OK, body includes SECRET DATA
##### Patches
Patched in `nuxt@4.4.6` and `nuxt@3.21.6` by [#35092](https://redirect.github.com/nuxt/nuxt/pull/35092). The Vue Router plugin now runs middleware and redirect handling for `page_*` islands (i.e. islands that originate from `.server.vue` files in `pages/`). The island handler propagates middleware-issued responses (`~renderResponse`), and a new `beforeResolve` guard returns HTTP 400 when the requested `page_<name>` does not match the route component the URL resolves to.
Non-page island components are unaffected - they continue to render without route middleware, by design.
##### Workarounds
If you cannot upgrade immediately:
- Enforce authentication inside the `.server.vue` page itself, not via route middleware. Read the session from `useRequestEvent()` and `throw createError({ statusCode: 401 })` (or redirect) before returning data. This is the recommended pattern for islands regardless of this advisory.
- Disable `experimental.componentIslands` if your app does not use the feature.
- If your app must keep route-middleware-only auth, gate the `/__nuxt_island/page_*` URL prefix at your reverse proxy or in a server middleware.
#### Severity
- CVSS Score: 6.3 / 10 (Medium)
- Vector String: `CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N`
#### References
- [https://github.com/nuxt/nuxt/security/advisories/GHSA-hg3f-28rg-4jxj](https://redirect.github.com/nuxt/nuxt/security/advisories/GHSA-hg3f-28rg-4jxj)
- [https://github.com/nuxt/nuxt/issues/19772](https://redirect.github.com/nuxt/nuxt/issues/19772)
- [https://github.com/nuxt/nuxt/pull/35092](https://redirect.github.com/nuxt/nuxt/pull/35092)
- [https://nvd.nist.gov/vuln/detail/CVE-2026-47200](https://nvd.nist.gov/vuln/detail/CVE-2026-47200)
- [https://github.com/advisories/GHSA-hg3f-28rg-4jxj](https://redirect.github.com/advisories/GHSA-hg3f-28rg-4jxj)
This data is provided by the [GitHub Advisory Database](https://redirect.github.com/advisories/GHSA-hg3f-28rg-4jxj) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</name></hashid></routename></anyhash></routename></routename>
Nuxt: URL-handling weaknesses in navigateTo and reloadNuxtApp: SSR open redirect, client-side script execution via the open option, and protocol-relative bypass in reloadNuxtApp
CVE-2026-56326 / GHSA-c9cv-mq2m-ppp3
More information
#### Details
##### Summary
Three weaknesses in Nuxt's client-navigation URL handling, all reachable
from documented public APIs (`navigateTo` and `reloadNuxtApp`):
1. **SSR open redirect in `navigateTo` via path-normalisation bypass.**
`navigateTo` decided whether a target was external by inspecting the raw
input with `hasProtocol(..., { acceptRelative: true })`. Inputs such as
`/..//evil.com`, `/.//evil.com`, `/%2e%2e//evil.com`, or
`/app/..//evil.com` slipped past that check because they start with
`/`, but WHATWG URL parsing then normalised them to the
protocol-relative pathname `//evil.com`. The normalised value was
written to the `Location` response header and into the
`<meta http-equiv="refresh">` body of the SSR redirect page, so a
victim's browser would resolve the redirect cross-origin to the
attacker's host.
2. **Client-side script execution via `navigateTo({ open: ... })`.** The
client-side early-open handler called `window.open(toPath, ...)` without
applying the `isScriptProtocol` check that gates the normal `navigateTo`
path. A target of `javascript:...` (or another script-capable scheme)
passed to `navigateTo(url, { open: { ... } })` therefore executed in the
application's origin instead of being rejected.
3. **Open redirect in `reloadNuxtApp` via protocol-relative bypass.**
`reloadNuxtApp({ path })` rejects script-capable protocols by parsing
the path with `new URL(path, window.location.href)` and checking the
resolved `protocol` against `isScriptProtocol`. Protocol-relative paths
such as `//evil.com` resolve to the current page's protocol (`https:`),
which passes that check; the value is then assigned to
`window.location.href`, which the browser treats as a cross-origin
redirect. This is the same protocol-relative bypass family as (1), in
a different sink.
##### Impact
For (1), the practical risk is phishing or OAuth-code theft against any
Nuxt app that forwards user-controlled input (for example a `?next=`
query parameter on a login route) into `navigateTo` on the server. The
framework documents that `navigateTo` blocks external hosts unless
`external: true` is passed, so maintainers commonly rely on it as the
safe path for post-login redirects.
For (2), any app that passes a user-controlled URL into
`navigateTo(url, { open: { ... } })` was vulnerable to reflected XSS in
the application's first-party origin.
For (3), any app that forwards user-controlled input into
`reloadNuxtApp({ path })` could be redirected cross-origin for phishing
or OAuth-code theft, even on releases that already shipped the
`isScriptProtocol` guard added by [#35115](https://redirect.github.com/nuxt/nuxt/pull/35115).
##### Patches
Fixed in `nuxt@4.4.7` and backported to `nuxt@3.21.7`. The three sinks
are addressed by:
- Path-normalisation bypass in `navigateTo`:
- 4.x: commit [`2cce6fb0`](https://redirect.github.com/nuxt/nuxt/commit/2cce6fb02e621196d56df92e05594e07469b5a6d)
- 3.x: commit [`1f2dd5e7`](https://redirect.github.com/nuxt/nuxt/commit/1f2dd5e78c77576437138e97671965573c232835)
- `navigateTo({ open })` script-protocol guard:
- 4.x: [#35206](https://redirect.github.com/nuxt/nuxt/pull/35206) (commit [`3394716d`](https://redirect.github.com/nuxt/nuxt/commit/3394716d4a913cba904b028df5338f2aead50032))
- 3.x: commit [`62fc32ed`](https://redirect.github.com/nuxt/nuxt/commit/62fc32eddf648b00a3890141e0235d2a222b024d)
- Protocol-relative bypass in `reloadNuxtApp`:
- 4.x: commit [`e447a793`](https://redirect.github.com/nuxt/nuxt/commit/e447a793c47766834f7497f8412a76cd56fd8ee1)
- 3.x: commit [`6497d99d`](https://redirect.github.com/nuxt/nuxt/commit/6497d99dd106254abd089f6a263d7773869a343b)
##### Workarounds
- For (1): validate redirect targets before passing them to `navigateTo`,
for example reject any input where
`new URL(target, 'http://localhost').pathname` starts with `//`, or
only accept a known allow-list of paths.
- For (2): reject any user-controlled URL whose protocol is not in an
allow-list (typically just `http:` and `https:`) before passing it to
`navigateTo({ open: ... })`.
- For (3): same shape as (1). Reject paths starting with `//` (or where
`new URL(path, window.location.href).host !== window.location.host`)
before passing to `reloadNuxtApp({ path })`.
##### References
- CWE-601: URL Redirection to Untrusted Site ('Open Redirect')
- CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
##### Credits
Reported by Anthropic / Claude as `ANT-2026-S08HN6DH` through Anthropic's
coordinated vulnerability disclosure programme.
The `reloadNuxtApp` protocol-relative bypass (sink 3) was independently
reported by [@alcls01111](https://redirect.github.com/alcls01111) via GitHub's
coordinated disclosure flow (`GHSA-w7fp-2cfv-4837`), closed as a
duplicate of this advisory.
#### Severity
- CVSS Score: 5.1 / 10 (Medium)
- Vector String: `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:L/VI:L/VA:N/SC:N/SI:L/SA:N`
#### References
- [https://github.com/nuxt/nuxt/security/advisories/GHSA-c9cv-mq2m-ppp3](https://redirect.github.com/nuxt/nuxt/security/advisories/GHSA-c9cv-mq2m-ppp3)
- [https://github.com/nuxt/nuxt/pull/35115](https://redirect.github.com/nuxt/nuxt/pull/35115)
- [https://github.com/nuxt/nuxt/pull/35206](https://redirect.github.com/nuxt/nuxt/pull/35206)
- [https://github.com/nuxt/nuxt/commit/1f2dd5e78c77576437138e97671965573c232835](https://redirect.github.com/nuxt/nuxt/commit/1f2dd5e78c77576437138e97671965573c232835)
- [https://github.com/nuxt/nuxt/commit/2cce6fb02e621196d56df92e05594e07469b5a6d](https://redirect.github.com/nuxt/nuxt/commit/2cce6fb02e621196d56df92e05594e07469b5a6d)
- [https://github.com/nuxt/nuxt/commit/3394716d4a913cba904b028df5338f2aead50032](https://redirect.github.com/nuxt/nuxt/commit/3394716d4a913cba904b028df5338f2aead50032)
- [https://github.com/nuxt/nuxt/commit/62fc32eddf648b00a3890141e0235d2a222b024d](https://redirect.github.com/nuxt/nuxt/commit/62fc32eddf648b00a3890141e0235d2a222b024d)
- [https://github.com/nuxt/nuxt/commit/6497d99dd106254abd089f6a263d7773869a343b](https://redirect.github.com/nuxt/nuxt/commit/6497d99dd106254abd089f6a263d7773869a343b)
- [https://github.com/nuxt/nuxt/commit/e447a793c47766834f7497f8412a76cd56fd8ee1](https://redirect.github.com/nuxt/nuxt/commit/e447a793c47766834f7497f8412a76cd56fd8ee1)
- [https://github.com/advisories/GHSA-c9cv-mq2m-ppp3](https://redirect.github.com/advisories/GHSA-c9cv-mq2m-ppp3)
This data is provided by the [GitHub Advisory Database](https://redirect.github.com/advisories/GHSA-c9cv-mq2m-ppp3) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
Nuxt: Route-rule middleware bypass via case-sensitivity mismatch between vue-router and the routeRules matcher
CVE-2026-53721 / GHSA-mm7m-92g8-7m47
More information
#### Details
##### Impact
Nuxt looks up `routeRules` for the current navigation by calling
`getRouteRules({ path: to.path })` from the page-router plugin and the
no-pages router plugin. The compiled `routeRules` matcher (built on
`rou3`) performs case-sensitive matching, while vue-router is configured
with its default `sensitive: false` and matches paths case-insensitively.
The two routers therefore disagree on which rules apply to a given
request path: vue-router still matches the page record for
`/Admin/dashboard`, but the `routeRules` lookup for the same path
returns no match. Any `appMiddleware` declared via `routeRules` is never
added to the middleware set and never runs, on both SSR and client
navigations. The same path skips other path-keyed route rules in the
same way (`ssr`, `redirect`, `appLayout`, and the prerender / payload
hints used client-side).
For applications using `routeRules` with `appMiddleware` as an
authorization gate (a documented pattern), an attacker can flip the case
of any static segment in a protected URL (for example `/Admin/dashboard`
instead of `/admin/dashboard`) to render the protected page with the
middleware skipped. The server returns the fully server-rendered page
including any `useFetch` / `useAsyncData` results captured during SSR.
This is an instance of CWE-178 (Improper Handling of Case Sensitivity)
leading to CWE-863 (Incorrect Authorization) for apps that treat
`appMiddleware` as an authorization boundary.
##### Mitigating factors
- Only affects apps that use `routeRules.appMiddleware`. The more
idiomatic `definePageMeta({ middleware })` is bound to the matched
route record and is unaffected.
- Nuxt route middleware is documented as an app-layer concern, not a
server-side auth boundary; well-built apps enforce authorization
again at the API / data-fetching layer.
- Apps that explicitly set `router.options.sensitive = true` are not
affected.
##### Patches
Fixed in `nuxt@4.4.7` (commit [`07e39cd6`](https://redirect.github.com/nuxt/nuxt/commit/07e39cd6f26e407b4192b7865bd17bc44536b9bb)) and backported to `nuxt@3.21.7` (commit [`3f3e3fa7`](https://redirect.github.com/nuxt/nuxt/commit/3f3e3fa7b5eec8e495f4f8ce0a54813a8875a11e)). The fix normalizes the path used for `routeRules` lookups so it matches vue-router's default case-insensitive semantics.
##### Workarounds
Until you can upgrade, you can mitigate by either:
1. Setting `router.options.sensitive = true` so vue-router matches
case-sensitively (this changes route-matching behaviour app-wide).
2. Moving security-critical middleware off `routeRules.appMiddleware`
and onto `definePageMeta({ middleware: [...] })` on the protected
page components, which is bound to the matched record.
3. Enforcing authorization at the API / data-fetching layer (which you
should be doing in any case).
##### Credit
Reported by Anthropic / Claude through Anthropic's coordinated
vulnerability disclosure process. Reference: ANT-2026-9FSEBYMC.
#### Severity
- CVSS Score: 8.8 / 10 (High)
- Vector String: `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N`
#### References
- [https://github.com/nuxt/nuxt/security/advisories/GHSA-mm7m-92g8-7m47](https://redirect.github.com/nuxt/nuxt/security/advisories/GHSA-mm7m-92g8-7m47)
- [https://nvd.nist.gov/vuln/detail/CVE-2026-53721](https://nvd.nist.gov/vuln/detail/CVE-2026-53721)
- [https://github.com/nuxt/nuxt/commit/07e39cd6f26e407b4192b7865bd17bc44536b9bb](https://redirect.github.com/nuxt/nuxt/commit/07e39cd6f26e407b4192b7865bd17bc44536b9bb)
- [https://github.com/nuxt/nuxt/commit/3f3e3fa7b5eec8e495f4f8ce0a54813a8875a11e](https://redirect.github.com/nuxt/nuxt/commit/3f3e3fa7b5eec8e495f4f8ce0a54813a8875a11e)
- [https://github.com/advisories/GHSA-mm7m-92g8-7m47](https://redirect.github.com/advisories/GHSA-mm7m-92g8-7m47)
This data is provided by the [GitHub Advisory Database](https://redirect.github.com/advisories/GHSA-mm7m-92g8-7m47) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
Nuxt dev server vite-node IPC socket is world-connectable on Linux
GHSA-534h-c3cw-v3h9
More information
#### Details
##### Impact
When running `nuxt dev` on Linux (Node.js 20+, outside Docker / StackBlitz), Nuxt's internal vite-node IPC server binds to a Linux abstract-namespace Unix socket (`\0nuxt-vite-node-<pid>-<ts>.sock`). Abstract sockets have no filesystem inode and therefore no permission bits: any local UID on the host that can read `/proc/net/unix` can enumerate the socket and connect to it.
The IPC server does not perform any peer-credential or shared-secret check before dispatching requests. The `module` request type passes its `moduleId` field straight into Vite's SSR `fetchModule()`, which is not gated by Vite's HTTP-layer `server.fs.allow` deny-list. A co-resident unprivileged local user can therefore request paths like `/home/<dev>/project/.env?raw` or `~/.ssh/id_rsa?raw` and read the developer's secrets through the dev server's SSR plugin pipeline. The `resolve` request type additionally enables filesystem probing.
This affects developers running `nuxt dev` on shared multi-tenant Linux hosts (lab machines, shared bastions, CI runners shared between jobs without per-job container isolation). It does not affect:
- Production builds (`nuxt build` / `nuxt start`). The IPC server only runs in development.
- macOS or Windows developers.
- Docker / StackBlitz environments, which already fall back to a filesystem socket.
- Single-user laptops or per-job containerised CI.
##### Patches
Fixed in `nuxt@4.4.7` (commit [`1f9f4767`](https://redirect.github.com/nuxt/nuxt/commit/1f9f4767a8725104da9bee872bb8d35246f25ae5)) and backported to `nuxt@3.21.7` (commit [`c293bf95`](https://redirect.github.com/nuxt/nuxt/commit/c293bf9503ccb3bc9559bff4a1f592f99063c9ea)).
The fix removes the abstract-namespace branch entirely. The IPC server now always binds to a filesystem Unix socket under the OS temp directory and explicitly `chmod 0600`s it after `listen()`, restricting connections to the owning UID. If the chmod fails for any reason, the server closes rather than serve requests on an unrestricted channel.
##### Workarounds
If you cannot upgrade immediately on an affected host:
- Run `nuxt dev` inside a container or VM with no other tenants. Docker already triggers the filesystem-socket fallback in vulnerable versions and that fallback is unaffected.
- Bind the dev process to a single-user namespace (`unshare -U`, rootless containers).
- Restrict `/proc/net/unix` visibility via `hidepid=2` mount options where applicable, though this is partial mitigation only.
##### References
- Affected file: `packages/vite/src/plugins/vite-node.ts`
- CWE-276: Incorrect Default Permissions
##### Credit
Reported by Anthropic / Claude as part of Anthropic's coordinated vulnerability disclosure programme, reference ANT-2026-MSNKZFAT. Thanks to the Anthropic security team for the report and the detailed reproduction.
Independently reported by [@alcls01111](https://redirect.github.com/alcls01111) via GitHub's coordinated disclosure flow (`GHSA-5gvc-46gq-948j`), closed as a duplicate of this advisory.
#### Severity
- CVSS Score: 5.5 / 10 (Medium)
- Vector String: `CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N`
#### References
- [https://github.com/nuxt/nuxt/security/advisories/GHSA-534h-c3cw-v3h9](https://redirect.github.com/nuxt/nuxt/security/advisories/GHSA-534h-c3cw-v3h9)
- [https://github.com/nuxt/nuxt/commit/1f9f4767a8725104da9bee872bb8d35246f25ae5](https://redirect.github.com/nuxt/nuxt/commit/1f9f4767a8725104da9bee872bb8d35246f25ae5)
- [https://github.com/nuxt/nuxt/commit/c293bf9503ccb3bc9559bff4a1f592f99063c9ea](https://redirect.github.com/nuxt/nuxt/commit/c293bf9503ccb3bc9559bff4a1f592f99063c9ea)
- [https://github.com/advisories/GHSA-534h-c3cw-v3h9](https://redirect.github.com/advisories/GHSA-534h-c3cw-v3h9)
This data is provided by the [GitHub Advisory Database](https://redirect.github.com/advisories/GHSA-534h-c3cw-v3h9) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</dev></ts></pid>
Nuxt: Reflected XSS in <NuxtLink> via unsanitised javascript: or data: URL
CVE-2026-53722 / GHSA-934w-87qh-qr26
More information
#### Details
##### Summary
`<nuxtlink>` did not validate the URL scheme of values bound to its `to` or `href` props before rendering them into the `href` attribute of the underlying `` element. When an application binds attacker-controlled input (a query parameter, a CMS field, a user-supplied profile URL) to `<nuxtlink :to="">` or `:href`, the attacker can supply a `javascript:` or `vbscript:` URL that is reflected verbatim into the rendered markup. Clicking the link executes the supplied script in the origin of the Nuxt application, resulting in reflected DOM-based cross-site scripting. A `data:text/html,...` payload reflected through the same sink does not execute in the application's origin but enables a same-tab phishing surface anchored to a legitimate application link.
The same value was exposed to consumers of the component's `custom` slot via the `href` and `route.href` props, so applications that re-bind those values to their own anchors were affected identically.
Unlike the previously reported `navigateTo` issue (CVE-2024-34343), the sink here is the rendered anchor itself; the existing `isScriptProtocol` checks in `navigateTo` and `reloadNuxtApp` are not on the code path. The `onClick` handler intentionally returns early for external links so the browser's native protocol-based navigation runs.
##### Affected component
- File: `packages/nuxt/src/app/components/nuxt-link.ts`
- Sink: `h('a', { href: href.value, ... })` in the default render, plus the `href` / `route.href` props passed to the `custom` slot.
- Broken check: external auto-detection treated any `hasProtocol(path, { acceptRelative: true })` value as an "external link", then rendered the value directly as `</nuxtlink>` without rejecting script-capable protocols. There was no equivalent of the `navigateTo` `isScriptProtocol(protocol)` gate in this path.
##### Impact
Any Nuxt application that binds user-controlled values to `<nuxtlink :to="">` / `:href` was vulnerable. Common shapes: profile-link rendering (`<nuxtlink :to="user.website">`), "share this" / "open in new tab" handlers that pass through a query parameter, CMS-driven landing pages that render `<nuxtlink :to="cms.cta.url">`, and marketplace listings that show seller-supplied links.
For `javascript:` / `vbscript:` the primitive is reflected XSS in the application's first-party origin (session theft for non-`HttpOnly` cookies, CSRF token theft, account takeover via DOM rewriting, credential harvesting via fake login overlays). For `data:text/html,...` the attacker gets a same-tab phishing surface anchored to a legitimate application link.
##### Patches
Fixed in `nuxt@4.4.7` (commit [`0103ce06`](https://redirect.github.com/nuxt/nuxt/commit/0103ce06fbbbdfa079a7f020ef8ce00121eac4a3)) and backported to `nuxt@3.21.7` (commit [`53284043`](https://redirect.github.com/nuxt/nuxt/commit/53284043dc21210a25d629d1cec67d3ae557ffd0)). The fix sanitises the resolved external `href` before it is passed to `</nuxtlink></nuxtlink></nuxtlink>` or the `custom` slot: control characters and whitespace are stripped, leading `view-source:` prefixes are unwrapped, and any remaining script-capable scheme (per `isScriptProtocol`) causes the `href` to be replaced with an empty string.
##### Workarounds
Until you can upgrade, validate URLs at the source before binding them to `<nuxtlink :to="">` / `:href`. For example, only accept paths that start with `/` (and not `//`), or run user-supplied URLs through `new URL(value)` and reject anything whose `protocol` is not in an allow-list (typically `http:` and `https:`).
#### Severity
- CVSS Score: 5.1 / 10 (Medium)
- Vector String: `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N`
#### References
- [https://github.com/nuxt/nuxt/security/advisories/GHSA-934w-87qh-qr26](https://redirect.github.com/nuxt/nuxt/security/advisories/GHSA-934w-87qh-qr26)
- [https://nvd.nist.gov/vuln/detail/CVE-2026-53722](https://nvd.nist.gov/vuln/detail/CVE-2026-53722)
- [https://github.com/nuxt/nuxt/commit/0103ce06fbbbdfa079a7f020ef8ce00121eac4a3](https://redirect.github.com/nuxt/nuxt/commit/0103ce06fbbbdfa079a7f020ef8ce00121eac4a3)
- [https://github.com/nuxt/nuxt/commit/53284043dc21210a25d629d1cec67d3ae557ffd0](https://redirect.github.com/nuxt/nuxt/commit/53284043dc21210a25d629d1cec67d3ae557ffd0)
- [https://github.com/advisories/GHSA-934w-87qh-qr26](https://redirect.github.com/advisories/GHSA-934w-87qh-qr26)
This data is provided by the [GitHub Advisory Database](https://redirect.github.com/advisories/GHSA-934w-87qh-qr26) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</nuxtlink></nuxtlink>
Cross-site scripting via <noscript> slot content in Nuxt's head components</noscript>
GHSA-m3q2-p4fw-w38m
More information
#### Details
##### Impact
Nuxt's globally registered `<noscript>` component (from `@unhead/vue` head components, re-exported by Nuxt) wrote its default-slot content to the `innerHTML` of the `<noscript>` head tag, bypassing the HTML escaping that `{{ }}` interpolation normally applies in Vue templates.
Applications that placed untrusted, attacker-controllable data inside a `<noscript>` slot, for example:
:::vue
<noscript>{{ route.query.banner }}</noscript>
would emit that value unescaped inside `<noscript>` in the server-rendered HTML. With scripting enabled, the HTML parser treats `<noscript>` content in `` under the "in head noscript" insertion mode: any tag other than `link`, `meta`, `noframes`, or `style` implicitly closes `<noscript>` and is re-processed in the head. A payload such as `<script>...</script>` therefore escapes the element and executes in the document context.
Sibling head components (`<style>`, `<Title>`) were not affected because they already routed slot text through the safe `textContent` path.
##### Affected versions
All currently supported versions of `nuxt` that ship the `<NoScript>` global component.
##### Patches
Fixed in `nuxt@4.4.7` (commit [`4b054e9d`](https://redirect.github.com/nuxt/nuxt/commit/4b054e9d95f8daf366cb144b52782047c511a66e)) and backported to `nuxt@3.21.7` (commit [`7fea9fd6`](https://redirect.github.com/nuxt/nuxt/commit/7fea9fd687f1dacbfb63db5fae5839896b017a0e)). The fix escapes `<NoScript>` slot content with `escapeHtml` from `@vue/shared` and writes it to `textContent` rather than `innerHTML`. Slot content is now rendered as text; intentional markup inside `<NoScript>` is no longer parsed as HTML.
##### Workarounds
Until you can upgrade:
- Do not interpolate untrusted input into `<NoScript>` slots. Replace `<NoScript>{{ x }}</NoScript>` with a static string, or sanitise / HTML-escape `x` at the source.
- If you must render dynamic noscript content, write the tag yourself via `useHead({ noscript: [{ textContent: escapedValue }] })` after escaping `escapedValue`.
##### Credit
Reported to Anthropic's coordinated vulnerability disclosure pipeline by Claude (Anthropic's AI assistant) and triaged by the Anthropic security team. Reference: ANT-2026-4NJYDFFM.
Independently reported by [@​alcls01111](https://redirect.github.com/alcls01111) via GitHub's coordinated disclosure flow (`GHSA-8grp-wcq9-925q`), closed as a duplicate of this advisory.
#### Severity
- CVSS Score: 2.3 / 10 (Low)
- Vector String: `CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N`
#### References
- [https://github.com/nuxt/nuxt/security/advisories/GHSA-m3q2-p4fw-w38m](https://redirect.github.com/nuxt/nuxt/security/advisories/GHSA-m3q2-p4fw-w38m)
- [https://github.com/nuxt/nuxt/commit/4b054e9d95f8daf366cb144b52782047c511a66e](https://redirect.github.com/nuxt/nuxt/commit/4b054e9d95f8daf366cb144b52782047c511a66e)
- [https://github.com/nuxt/nuxt/commit/7fea9fd687f1dacbfb63db5fae5839896b017a0e](https://redirect.github.com/nuxt/nuxt/commit/7fea9fd687f1dacbfb63db5fae5839896b017a0e)
- [https://github.com/advisories/GHSA-m3q2-p4fw-w38m](https://redirect.github.com/advisories/GHSA-m3q2-p4fw-w38m)
This data is provided by the [GitHub Advisory Database](https://redirect.github.com/advisories/GHSA-m3q2-p4fw-w38m) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>
---
### Release Notes
<details>
<summary>nuxt/nuxt (nuxt)</summary>
### [`v3.21.7`](https://redirect.github.com/nuxt/nuxt/releases/tag/v3.21.7)
[Compare Source](https://redirect.github.com/nuxt/nuxt/compare/v3.21.6...v3.21.7)
> 3.21.7 is the a security hotfix release.
👉 make sure to check <https://github.com/nuxt/nuxt/security/advisories> to view open advisories resolved by this release.
#### 👉 Changelog
[compare changes](https://redirect.github.com/nuxt/nuxt/compare/v3.21.6...v3.21.7)
##### 🩹 Fixes
- **nitro:** Assign `noSSR` before deciding payload extraction ([#​35108](https://redirect.github.com/nuxt/nuxt/pull/35108))
- **vite:** Avoid filtering out dirs with shared prefix from `allowDirs` ([#​35112](https://redirect.github.com/nuxt/nuxt/pull/35112))
- **nuxt:** Use resolve from `pathe` for buildCache path boundary check ([#​35111](https://redirect.github.com/nuxt/nuxt/pull/35111))
- **nuxt:** Prevent sibling-directory traversal in test component wrapper ([#​35110](https://redirect.github.com/nuxt/nuxt/pull/35110))
- **nitro:** Pass event data to `isValid` in dev clipboard-copy listener ([#​35109](https://redirect.github.com/nuxt/nuxt/pull/35109))
- **nuxt:** Validate protocols in `reloadNuxtApp` path before reload ([#​35115](https://redirect.github.com/nuxt/nuxt/pull/35115))
- **vite:** Resolve vite `clientServer` with `ssr: false` ([#​34959](https://redirect.github.com/nuxt/nuxt/pull/34959))
- **vite:** Prefix public asset virtuals with null byte ([38d330179](https://redirect.github.com/nuxt/nuxt/commit/38d330179))
- **nuxt:** Handle missing payload in chunkError listener ([#​35155](https://redirect.github.com/nuxt/nuxt/pull/35155))
- **vite:** Close vite dev server on nuxt close ([d007d7060](https://redirect.github.com/nuxt/nuxt/commit/d007d7060))
- **kit,nuxt:** Handle cancelling prompts to install packages ([59821a5ca](https://redirect.github.com/nuxt/nuxt/commit/59821a5ca))
- **nuxt:** Await in-lifght template generation when closing nuxt ([#​35181](https://redirect.github.com/nuxt/nuxt/pull/35181))
- **webpack:** Surface compilation errors when stats.toString is empty ([71dccff2b](https://redirect.github.com/nuxt/nuxt/commit/71dccff2b))
- **kit:** Improve TS extension stripping/substitutions ([#​35233](https://redirect.github.com/nuxt/nuxt/pull/35233))
- **nuxt:** Preserve `.d.mts`/`.d.cts` in `resolveTypePaths` ([#​35235](https://redirect.github.com/nuxt/nuxt/pull/35235))
- **nuxt:** Reject prototype-chain keys in the island registry ([#​35205](https://redirect.github.com/nuxt/nuxt/pull/35205))
- **nitro:** Gate chrome devtools workspace endpoint to local requests ([#​35201](https://redirect.github.com/nuxt/nuxt/pull/35201))
- **nuxt:** Escape props in `<NuxtClientFallback>` ssr output ([#​35199](https://redirect.github.com/nuxt/nuxt/pull/35199))
- **nuxt:** Apply `isScriptProtocol` guard to `navigateTo` open option ([#​35206](https://redirect.github.com/nuxt/nuxt/pull/35206))
- **rspack,webpack:** Require loopback host when missing same-origin signals ([#​35200](https://redirect.github.com/nuxt/nuxt/pull/35200))
- **nuxt:** Absolutely resolve `defu` in app config template ([40bedf0db](https://redirect.github.com/nuxt/nuxt/commit/40bedf0db))
- **nuxt:** Match route rules case-insensitively to mirror `vue-router` ([3f3e3fa7b](https://redirect.github.com/nuxt/nuxt/commit/3f3e3fa7b))
- **nuxt:** Escape `<NoScript>` slot content ([7fea9fd68](https://redirect.github.com/nuxt/nuxt/commit/7fea9fd68))
- **nuxt:** Block path-normalization open redirect in `navigateTo` ([1f2dd5e78](https://redirect.github.com/nuxt/nuxt/commit/1f2dd5e78))
- **nuxt:** Reject cross-origin paths in `reloadNuxtApp` ([6497d99dd](https://redirect.github.com/nuxt/nuxt/commit/6497d99dd))
- **vite:** Bind vite-node IPC to a permissioned filesystem socket ([c293bf950](https://redirect.github.com/nuxt/nuxt/commit/c293bf950))
- **nuxt:** Reject script-capable protocols in `<NuxtLink>` href ([53284043d](https://redirect.github.com/nuxt/nuxt/commit/53284043d))
- **nuxt:** Clarify page and layout usage warnings ([#​35184](https://redirect.github.com/nuxt/nuxt/pull/35184))
- **nuxt:** Do not absolutely resolve `defu` ([d11d7b1b5](https://redirect.github.com/nuxt/nuxt/commit/d11d7b1b5))
##### 📖 Documentation
- Edit for clarity and grammar ([#​35214](https://redirect.github.com/nuxt/nuxt/pull/35214))
- Add dedicated module dependencies page ([#​35171](https://redirect.github.com/nuxt/nuxt/pull/35171))
##### 🏡 Chore
- Use `execFileSync` for safety in release scripts ([9a455a658](https://redirect.github.com/nuxt/nuxt/commit/9a455a658))
- Assert there is always a tag ([8da21fba8](https://redirect.github.com/nuxt/nuxt/commit/8da21fba8))
- Fix type in test ([bc2837125](https://redirect.github.com/nuxt/nuxt/commit/bc2837125))
- Fix lychee dynamic composable exclude ([#​35119](https://redirect.github.com/nuxt/nuxt/pull/35119))
- Add autofix action tag in comment ([70eba297f](https://redirect.github.com/nuxt/nuxt/commit/70eba297f))
- Update renovate minimum release age ([27a6821a1](https://redirect.github.com/nuxt/nuxt/commit/27a6821a1))
##### ✅ Tests
- Update test for js payload rendering ([b51a80840](https://redirect.github.com/nuxt/nuxt/commit/b51a80840))
- Improve reliability of hmr test ([0078499f0](https://redirect.github.com/nuxt/nuxt/commit/0078499f0))
##### 🤖 CI
- Always run all tests for 4.x/3.x ([0519c0ade](https://redirect.github.com/nuxt/nuxt/commit/0519c0ade))
- Update to agentscan v1.8.0 ([#​35120](https://redirect.github.com/nuxt/nuxt/pull/35120))
- Automatically close PRs from automated accounts ([#​35161](https://redirect.github.com/nuxt/nuxt/pull/35161))
- Migrate from tibdex ([6277aedcb](https://redirect.github.com/nuxt/nuxt/commit/6277aedcb))
- Disable provenance-change enforcement in dependency-review ([1d4910eed](https://redirect.github.com/nuxt/nuxt/commit/1d4910eed))
- Add zizmor github actions check ([#​35089](https://redirect.github.com/nuxt/nuxt/pull/35089))
##### ❤️ Contributors
- Daniel Roe ([@​danielroe](https://redirect.github.com/danielroe))
- Matej Černý ([@​cernymatej](https://redirect.github.com/cernymatej))
- anton-gor-dev ([@​anton-gor-dev](https://redirect.github.com/anton-gor-dev))
- Julien Huang ([@​huang-julien](https://redirect.github.com/huang-julien))
- David Stack ([@​davidstackio](https://redirect.github.com/davidstackio))
- Noah3521 ([@​Noah3521](https://redirect.github.com/Noah3521))
- Matteo Gabriele ([@​MatteoGabriele](https://redirect.github.com/MatteoGabriele))
- Mohit Kumar ([@​mohitkum4r](https://redirect.github.com/mohitkum4r))
- Florian Heuberger ([@​Flo0806](https://redirect.github.com/Flo0806))
### [`v3.21.6`](https://redirect.github.com/nuxt/nuxt/releases/tag/v3.21.6)
[Compare Source](https://redirect.github.com/nuxt/nuxt/compare/v3.21.5...v3.21.6)
> 3.21.6 is the next patch release.
#### 👉 Changelog
[compare changes](https://redirect.github.com/nuxt/nuxt/compare/v3.21.5...v3.21.6)
##### 🩹 Fixes
- **nuxt:** Prefer our own builder/server deps ([#​35029](https://redirect.github.com/nuxt/nuxt/pull/35029))
- **nitro:** Add json extension to payload cache items ([#​35043](https://redirect.github.com/nuxt/nuxt/pull/35043))
- **nuxt:** Handle errors fetching app manifest ([#​35050](https://redirect.github.com/nuxt/nuxt/pull/35050))
- **nuxt:** Preserve `setPageLayout` props on same-path navigation ([#​35055](https://redirect.github.com/nuxt/nuxt/pull/35055))
- **vite:** Don't strip buildAssetsDir from vite-node SSR ids ([#​35040](https://redirect.github.com/nuxt/nuxt/pull/35040))
- **nuxt:** Mark `useLoadingIndicator` properties as readonly ([#​35062](https://redirect.github.com/nuxt/nuxt/pull/35062))
- **vite:** Strip queries in css inline styles map ([#​35067](https://redirect.github.com/nuxt/nuxt/pull/35067))
- **nuxt:** Encode html-significant characters in external redirect body ([#​35052](https://redirect.github.com/nuxt/nuxt/pull/35052))
- **nitro:** Validate island request hash matches props ([#​35077](https://redirect.github.com/nuxt/nuxt/pull/35077))
- **nitro:** Use regexp to strip query ([042b615e6](https://redirect.github.com/nuxt/nuxt/commit/042b615e6))
- **nitro:** Use `statusCode` for nitro v2 compatibility ([82dcd6a31](https://redirect.github.com/nuxt/nuxt/commit/82dcd6a31))
- **nuxt:** Render component-less parent routes during client-side nav ([#​35036](https://redirect.github.com/nuxt/nuxt/pull/35036))
- **nuxt:** Run middleware for page islands ([#​35092](https://redirect.github.com/nuxt/nuxt/pull/35092))
##### 💅 Refactors
- **rspack,webpack:** Extract same-origin check for dev middleware ([#​35051](https://redirect.github.com/nuxt/nuxt/pull/35051))
##### 📖 Documentation
- Remove CSB, set node 22 and use steps for clarity ([#​35066](https://redirect.github.com/nuxt/nuxt/pull/35066))
##### 🏡 Chore
- Ignore link-like syntax in code ([f9bf11b11](https://redirect.github.com/nuxt/nuxt/commit/f9bf11b11))
- Narrow engines.node in test ([5ed9a2691](https://redirect.github.com/nuxt/nuxt/commit/5ed9a2691))
- Remove unused import ([3a8bb0030](https://redirect.github.com/nuxt/nuxt/commit/3a8bb0030))
##### ✅ Tests
- Relax relative time assertion ([256513eb0](https://redirect.github.com/nuxt/nuxt/commit/256513eb0))
- Move build assets dir fixture out of `app/` ([6d2ac69ff](https://redirect.github.com/nuxt/nuxt/commit/6d2ac69ff))
##### 🤖 CI
- Clean up agent-scan workflow ([31590cf07](https://redirect.github.com/nuxt/nuxt/commit/31590cf07))
- Continue autofix workflow when `test:engines` fails ([958abb882](https://redirect.github.com/nuxt/nuxt/commit/958abb882))
- Improve workflows ([#​35088](https://redirect.github.com/nuxt/nuxt/pull/35088))
##### ❤️ Contributors
- Daniel Roe ([@​danielroe](https://redirect.github.com/danielroe))
- Julien Huang ([@​huang-julien](https://redirect.github.com/huang-julien))
- Damian Głowala ([@​DamianGlowala](https://redirect.github.com/DamianGlowala))
- Sébastien Chopin ([@​atinux](https://redirect.github.com/atinux))
- Adrien Foulon ([@​Tofandel](https://redirect.github.com/Tofandel))
### [`v3.21.5`](https://redirect.github.com/nuxt/nuxt/releases/tag/v3.21.5)
[Compare Source](https://redirect.github.com/nuxt/nuxt/compare/v3.21.4...v3.21.5)
> 3.21.5 is the next patch release.
#### 👉 Changelog
[compare changes](https://redirect.github.com/nuxt/nuxt/compare/v3.21.4...v3.21.5)
##### 🔥 Performance
- **kit:** Cache layer roots and short-circuit `isIgnored` relative ([#​35015](https://redirect.github.com/nuxt/nuxt/pull/35015))
##### 🩹 Fixes
- **nitro:** Correct payload route rule for `/` + override `ssr: true` ([#​34990](https://redirect.github.com/nuxt/nuxt/pull/34990))
- **nitro:** Break recursive rendering deadlocks during prerender ([#​34939](https://redirect.github.com/nuxt/nuxt/pull/34939))
- **vite:** Drop redundant css link when entry styles are inlined ([#​34950](https://redirect.github.com/nuxt/nuxt/pull/34950))
- **nuxt:** Only force suspense remount after first resolve ([#​34949](https://redirect.github.com/nuxt/nuxt/pull/34949))
- **kit:** Read `.env` before resolving nuxt schema ([#​34958](https://redirect.github.com/nuxt/nuxt/pull/34958))
- **nitro:** Preserve `serverHandlers` array after `nitro:config` ([#​34985](https://redirect.github.com/nuxt/nuxt/pull/34985))
- **vite:** Only consider CSS inlined when styles are actually emitted ([#​35006](https://redirect.github.com/nuxt/nuxt/pull/35006))
- **nuxt:** Handle string presets in auto-imports ([#​35013](https://redirect.github.com/nuxt/nuxt/pull/35013))
- **nuxt:** Correct island transform for server pages and 'deep' mode ([#​35005](https://redirect.github.com/nuxt/nuxt/pull/35005))
- **vite:** Inline css for non-island children of server components ([#​35001](https://redirect.github.com/nuxt/nuxt/pull/35001))
- **nuxt:** Defer head DOM updates until page transition finishes ([#​35016](https://redirect.github.com/nuxt/nuxt/pull/35016))
- **nuxt:** Explicitly freeze head during island plugin phase ([#​35010](https://redirect.github.com/nuxt/nuxt/pull/35010))
- **vite:** Inline css imported from non-vue js modules ([#​35020](https://redirect.github.com/nuxt/nuxt/pull/35020))
- **nitro:** Remove unused middleware ([fe857d36b](https://redirect.github.com/nuxt/nuxt/commit/fe857d36b))
##### 📖 Documentation
- Add warning about routing in server components ([#​34994](https://redirect.github.com/nuxt/nuxt/pull/34994))
##### 🏡 Chore
- Ignore pnpm cyclic workspace deps warn ([#​34998](https://redirect.github.com/nuxt/nuxt/pull/34998))
- Remove jiti from build steps ([#​35004](https://redirect.github.com/nuxt/nuxt/pull/35004))
- Fix lockfile ([48e56a509](https://redirect.github.com/nuxt/nuxt/commit/48e56a509))
- **nuxt:** Cast to nitro event handler type ([5b358ca19](https://redirect.github.com/nuxt/nuxt/commit/5b358ca19))
##### ✅ Tests
- Extract server components fixture + add some failing tests ([#​34995](https://redirect.github.com/nuxt/nuxt/pull/34995))
- Isolate `buildDir` per matrix project for shared fixtures ([#​35007](https://redirect.github.com/nuxt/nuxt/pull/35007))
- Split env testing into separate file ([fd4019cf8](https://redirect.github.com/nuxt/nuxt/commit/fd4019cf8))
- Use 3.x style tsconfig ([86625efad](https://redirect.github.com/nuxt/nuxt/commit/86625efad))
- Use more 3.x style tsconfigs ([4a9bde3f3](https://redirect.github.com/nuxt/nuxt/commit/4a9bde3f3))
- Correct import path ([133d5f6d7](https://redirect.github.com/nuxt/nuxt/commit/133d5f6d7))
- Update snapshots ([9fc42f788](https://redirect.github.com/nuxt/nuxt/commit/9fc42f788))
##### ❤️ Contributors
- Daniel Roe ([@​danielroe](https://redirect.github.com/danielroe))
- Harlan Wilton ([@​harlan-zw](https://redirect.github.com/harlan-zw))
- Jonazzzz ([@​Bombastickj](https://redirect.github.com/Bombastickj))
- Damian Głowala ([@​DamianGlowala](https://redirect.github.com/DamianGlowala))
- Florian Heuberger ([@​Flo0806](https://redirect.github.com/Flo0806))
### [`v3.21.4`](https://redirect.github.com/nuxt/nuxt/compare/v3.21.2...v3.21.4)
[Compare Source](https://redirect.github.com/nuxt/nuxt/compare/v3.21.2...v3.21.4)
</details>
---
### Configuration
📅 **Schedule**: (in timezone Europe/Paris)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Enabled.
♻ **Rebasing**: Whenever PR is behind base branch, 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 was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/e2e-test-quest/uuv).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xODUuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIzNS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
</style></noscript></noscript></noscript></noscript></noscript></noscript>
Ticket changed by: renovate[bot]
Ticket changed by: renovate[bot]