GitHub Advisoryadvisory · npm

GHSA-fx6j-w5w5-h468 Nuxt: Reflected XSS in `navigateTo()` external redirect

MEDIUM Published 2026-05-19 Modified 2026-07-08 Official page ↗
Aliases
CVE-2026-45669
Ecosystem
npm
Packages
nuxt
Severity
Moderate
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N
Weaknesses
CWE-83
Reviewed
2026-05-19

Affected packages

• npm nuxt: >= 3.4.3, < 3.21.6 → fixed in 3.21.6 • npm nuxt: >= 4.0.0-alpha.1, < 4.4.6 → fixed in 4.4.6

Description

Summary `navigateTo()` with `external: true` generates a server-side HTML redirect body containing a `` 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: ``, 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 "> ``` 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 `[email protected]` and `[email protected]` by #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 `` (a normalised URL with these characters is malformed and safe to refuse).

Related

Alias · CVE (1)

  • CVE-2026-45669 Nuxt is an open-source web development framework for Vue.js. vulnerability

Weakness · CWE (1)

  • CWE-83 Improper Neutralization of Script in Attributes in a Web Page weakness

References