Advisory Database
  • Advisories
  • Dependency Scanning
  1. npm
  2. ›
  3. @nuxtjs/mdc
  4. ›
  5. CVE-2026-63671

CVE-2026-63671: @nuxtjs/mdc's URL sanitizer misses SVG xlink:href and data:text/html, allowing XSS from untrusted markdown at the default configuration

September 16, 2026

@nuxtjs/mdc renders untrusted markdown (including raw HTML) to a Vue component tree. Across two prior advisories it added a URL/attribute sanitizer to block dangerous links in that HTML: validateProps / validateProp and an unsafeLinkPrefix deny-list (dist/runtime/parser/utils/props.js). The sanitizer runs at parse time (dist/runtime/parser/compiler.js) and parseMarkdown enables raw HTML by default (allowDangerousHtml: true, dist/runtime/parser/options.js), so the sanitizer is the only barrier and it applies with no configuration required.

Two sibling vectors bypass that sanitizer at the default configuration:

  1. SVG anchor xlink:href. validateProp only scheme-checks attributes named exactly href or src:
if (attribute === "href" || attribute === "src") return isAnchorLinkAllowed(value);
return true;

An xlink:href (parsed to the hast property xLinkHref) is neither, so a javascript: URL on an SVG <a> is passed through. The renderer maps the property back to the real attribute (MDCRenderer.vue: find(html, "xLinkHref").attribute is xlink:href), so the output element is <a xlink:href="javascript:...">. Clicking it runs the script in the page origin. Plain <a href="javascript:..."> is correctly stripped, which is what makes this the un-patched sibling.

  1. <iframe src="data:text/html,...">. data:text/html is present in unsafeLinkPrefix, but the check compares it against url.protocol:
if (unsafeLinkPrefix.some((prefix) => url.protocol.toLowerCase().startsWith(prefix))) return false;

For any data URI url.protocol is just "data:", so "data:".startsWith("data:text/html") is always false. Every data:text/* entry in the deny-list is therefore dead code, and <iframe src="data:text/html,<script>...</script>"> is allowed (iframe is not in the render-time dangerousTags, which is only ["script","base"]). The framed document executes script in an opaque origin. For contrast, srcdoc and object are blocked, so this is a precise gap rather than a general absence of filtering.

References

  • github.com/advisories/GHSA-mxm6-v9r6-r94c
  • github.com/nuxt-content/mdc/commit/61d636c2983f021288e4fc5c4006733b38cf0d53
  • github.com/nuxt-content/mdc/pull/491
  • github.com/nuxt-content/mdc/releases/tag/v0.22.1
  • github.com/nuxt-content/mdc/security/advisories/GHSA-mxm6-v9r6-r94c
  • nvd.nist.gov/vuln/detail/CVE-2026-63671

Code Behaviors & Features

Detect and mitigate CVE-2026-63671 with GitLab Dependency Scanning

Secure your software supply chain by verifying that all open source dependencies used in your projects contain no disclosed vulnerabilities. Dependency Scanning using SBOM also detects vulnerabilities from proprietary advisories that this site does not include. Learn more about Dependency Scanning using SBOM →

Affected versions

All versions before 0.22.1

Fixed versions

  • 0.22.1

Solution

Upgrade to version 0.22.1 or above.

Impact 8.1 HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N

Learn more about CVSS

Weakness

  • CWE-184: Incomplete List of Disallowed Inputs
  • CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

Source file

npm/@nuxtjs/mdc/CVE-2026-63671.yml

Spotted a mistake? Edit the file on GitLab.

  • Site Repo
  • About GitLab
  • Terms
  • Privacy Statement
  • Contact

Page generated Sun, 08 Nov 2026 00:15:50 +0000.