{"id":"GHSA-934w-87qh-qr26","summary":"Nuxt: Reflected XSS in `\u003cNuxtLink\u003e` via unsanitised `javascript:` or `data:` URL","details":"### Summary\n\n`\u003cNuxtLink\u003e` 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 `\u003ca\u003e` element. When an application binds attacker-controlled input (a query parameter, a CMS field, a user-supplied profile URL) to `\u003cNuxtLink :to\u003e` 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.\n\nThe 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.\n\nUnlike 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.\n\n### Affected component\n\n- File: `packages/nuxt/src/app/components/nuxt-link.ts`\n- Sink: `h('a', { href: href.value, ... })` in the default render, plus the `href` / `route.href` props passed to the `custom` slot.\n- Broken check: external auto-detection treated any `hasProtocol(path, { acceptRelative: true })` value as an \"external link\", then rendered the value directly as `\u003ca href\u003e` without rejecting script-capable protocols. There was no equivalent of the `navigateTo` `isScriptProtocol(protocol)` gate in this path.\n\n### Impact\n\nAny Nuxt application that binds user-controlled values to `\u003cNuxtLink :to\u003e` / `:href` was vulnerable. Common shapes: profile-link rendering (`\u003cNuxtLink :to=\"user.website\"\u003e`), \"share this\" / \"open in new tab\" handlers that pass through a query parameter, CMS-driven landing pages that render `\u003cNuxtLink :to=\"cms.cta.url\"\u003e`, and marketplace listings that show seller-supplied links.\n\nFor `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.\n\n### Patches\n\nFixed in `nuxt@4.4.7` (commit [`0103ce06`](https://github.com/nuxt/nuxt/commit/0103ce06fbbbdfa079a7f020ef8ce00121eac4a3)) and backported to `nuxt@3.21.7` (commit [`53284043`](https://github.com/nuxt/nuxt/commit/53284043dc21210a25d629d1cec67d3ae557ffd0)). The fix sanitises the resolved external `href` before it is passed to `\u003ca\u003e` 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.\n\n### Workarounds\n\nUntil you can upgrade, validate URLs at the source before binding them to `\u003cNuxtLink :to\u003e` / `: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:`).","aliases":["CVE-2026-53722"],"modified":"2026-08-14T19:00:07.575442969Z","published":"2026-06-16T13:49:36Z","database_specific":{"severity":"MODERATE","github_reviewed":true,"github_reviewed_at":"2026-06-16T13:49:36Z","nvd_published_at":"2026-06-12T15:16:31Z","cwe_ids":["CWE-79","CWE-83"]},"references":[{"type":"WEB","url":"https://github.com/nuxt/nuxt/security/advisories/GHSA-934w-87qh-qr26"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-53722"},{"type":"WEB","url":"https://github.com/nuxt/nuxt/commit/0103ce06fbbbdfa079a7f020ef8ce00121eac4a3"},{"type":"WEB","url":"https://github.com/nuxt/nuxt/commit/53284043dc21210a25d629d1cec67d3ae557ffd0"},{"type":"PACKAGE","url":"https://github.com/nuxt/nuxt"}],"affected":[{"package":{"name":"nuxt","ecosystem":"npm","purl":"pkg:npm/nuxt"},"ranges":[{"type":"SEMVER","events":[{"introduced":"4.0.0"},{"fixed":"4.4.7"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-934w-87qh-qr26/GHSA-934w-87qh-qr26.json"}},{"package":{"name":"nuxt","ecosystem":"npm","purl":"pkg:npm/nuxt"},"ranges":[{"type":"SEMVER","events":[{"introduced":"3.0.0"},{"fixed":"3.21.7"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-934w-87qh-qr26/GHSA-934w-87qh-qr26.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V4","score":"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"}]}