Nuxt: Reflected XSS in `<NuxtLink>` via unsanitised `javascript:` or `data:` URLGHSA-934w-87qh-qr26
Fix: nuxt/nuxt@0103ce0GHSA-934w-87qh-qr26 is a Cross-site Scripting (XSS) vulnerability in nuxt. A fix is available for nuxt — see the affected versions and patch details below.
Exploitation Status
No confirmed exploitation observed yet
- CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.
Exploitation and automatability from CISA’s SSVC triage for GHSA-934w-87qh-qr26.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
Real-World Exposure
How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.
nuxtnpmDescription
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 <a> 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 thehref/route.hrefprops passed to thecustomslot. - Broken check: external auto-detection treated any
hasProtocol(path, { acceptRelative: true })value as an "external link", then rendered the value directly as<a href>without rejecting script-capable protocols. There was no equivalent of thenavigateToisScriptProtocol(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 [email protected] (commit 0103ce06) and backported to [email protected] (commit 53284043). The fix sanitises the resolved external href before it is passed to <a> 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:).
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 📦npm | nuxt | ≥ 4.0.0&&< 4.4.7 | 4.4.7npm install nuxt@4.4.7 |
| 📦npm | nuxt | ≥ 3.0.0&&< 3.21.7 | 3.21.7npm install nuxt@3.21.7 |
Affected Products
nuxtnuxtDetection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for nuxt, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update nuxt to 4.4.7 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-934w-87qh-qr26 is resolved across your whole dependency graph.
Workarounds
Escape or sanitise the affected output on the server side rather than relying on client-side filtering, and add a Content-Security-Policy that blocks inline script execution so injected markup cannot run even if it reaches the page.
Frequently Asked Questions
Is GHSA-934w-87qh-qr26 in your dependencies?
Find it across npm, including transitive dependencies.