ghsa-7rqq-prvp-x9jh
Vulnerability from github
Published
2025-08-19 20:16
Modified
2025-08-22 22:52
Summary
Mermaid improperly sanitizes sequence diagram labels leading to XSS
Details

Summary

In the default configuration of mermaid 11.9.0, user supplied input for sequence diagram labels is passed to innerHTML during calculation of element size, causing XSS.

Details

Sequence diagram node labels with KaTeX delimiters are passed through calculateMathMLDimensions. This method passes the full label to innerHTML which allows allows malicious users to inject arbitrary HTML and cause XSS when mermaid-js is used in it's default configuration (with KaTeX support enabled).

The vulnerability lies here:

ts export const calculateMathMLDimensions = async (text: string, config: MermaidConfig) => { text = await renderKatex(text, config); const divElem = document.createElement('div'); divElem.innerHTML = text; // XSS sink, text has not been sanitized. divElem.id = 'katex-temp'; divElem.style.visibility = 'hidden'; divElem.style.position = 'absolute'; divElem.style.top = '0'; const body = document.querySelector('body'); body?.insertAdjacentElement('beforeend', divElem); const dim = { width: divElem.clientWidth, height: divElem.clientHeight }; divElem.remove(); return dim; };

The calculateMathMLDimensions method was introduced in 5c69e5fdb004a6d0a2abe97e23d26e223a059832 two years ago, which was released in Mermaid 10.9.0.

PoC

Render the following diagram and observe the modified DOM.

sequenceDiagram participant A as Alice<img src="x" onerror="document.write(`xss on ${document.domain}`)">$$\\text{Alice}$$ A->>John: Hello John, how are you? Alice-)John: See you later!

Here is a PoC on mermaid.live: https://mermaid.live/edit#pako:eNpVUMtOwzAQ_BWzyoFKaRTyaFILiio4IK7ckA-1km1iKbaLY6spUf4dJ0AF68uOZ2dm7REqXSNQ6PHDoarwWfDGcMkUudaJGysqceLKkj3hPdl3osJ7IRvSm-qBwcCAaIXGaONRrSsnUdnobITF28PQ954lwXglai25UNNhxWAXBMyXxcGOi-3kL_5k79e73atuFSUv2HWazH1IWn0m3CC5aPf4b3p2WK--BW-4DJCOWzQ3TM0HQmiMqIFa4zAEicZv4iGMsw0D26JEBtS3NR656ywDpiYv869_11r-Ko12TQv0yLveI3eqfcjP111HUNVonrRTFuhdsVgAHWEAmuRxlG7SuEzKMi-yJAnhAjTLIk_EcbFJtuk2y9MphM8lM47KIp--AOZghtU

Impact

XSS on all sites that use mermaid and render user supplied diagrams without further sanitization.

Remediation

The value of the text argument for the calculateMathMLDimensions method needs to be sanitized before getting passed on to innerHTML.

Show details on source website


{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "mermaid"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "11.0.0-alpha.1"
            },
            {
              "fixed": "11.10.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "mermaid"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "10.9.0-rc.1"
            },
            {
              "fixed": "10.9.4"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-54881"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-79"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-08-19T20:16:58Z",
    "nvd_published_at": "2025-08-19T17:15:41Z",
    "severity": "MODERATE"
  },
  "details": "### Summary\nIn the default configuration of mermaid 11.9.0, user supplied input for sequence diagram labels is passed to `innerHTML` during calculation of element size, causing XSS.\n\n### Details\nSequence diagram node labels with KaTeX delimiters are passed through `calculateMathMLDimensions`. This method passes the full label to `innerHTML` which allows allows malicious users to inject arbitrary HTML and cause XSS when mermaid-js is used in it\u0027s default configuration (with KaTeX support enabled). \n\nThe vulnerability lies here:\n\n```ts\nexport const calculateMathMLDimensions = async (text: string, config: MermaidConfig) =\u003e {\n  text = await renderKatex(text, config);\n  const divElem = document.createElement(\u0027div\u0027);\n  divElem.innerHTML = text; // XSS sink, text has not been sanitized.\n  divElem.id = \u0027katex-temp\u0027;\n  divElem.style.visibility = \u0027hidden\u0027;\n  divElem.style.position = \u0027absolute\u0027;\n  divElem.style.top = \u00270\u0027;\n  const body = document.querySelector(\u0027body\u0027);\n  body?.insertAdjacentElement(\u0027beforeend\u0027, divElem);\n  const dim = { width: divElem.clientWidth, height: divElem.clientHeight };\n  divElem.remove();\n  return dim;\n};\n```\n\nThe `calculateMathMLDimensions` method was introduced in 5c69e5fdb004a6d0a2abe97e23d26e223a059832 two years ago, which was released in [Mermaid 10.9.0](https://github.com/mermaid-js/mermaid/releases/tag/v10.9.0).\n\n### PoC\nRender the following diagram and observe the modified DOM.\n\n```\nsequenceDiagram\n    participant A as Alice\u003cimg src=\"x\" onerror=\"document.write(`xss on ${document.domain}`)\"\u003e$$\\\\text{Alice}$$\n    A-\u003e\u003eJohn: Hello John, how are you?\n    Alice-)John: See you later!\n```\n\nHere is a PoC on mermaid.live: https://mermaid.live/edit#pako:eNpVUMtOwzAQ_BWzyoFKaRTyaFILiio4IK7ckA-1km1iKbaLY6spUf4dJ0AF68uOZ2dm7REqXSNQ6PHDoarwWfDGcMkUudaJGysqceLKkj3hPdl3osJ7IRvSm-qBwcCAaIXGaONRrSsnUdnobITF28PQ954lwXglai25UNNhxWAXBMyXxcGOi-3kL_5k79e73atuFSUv2HWazH1IWn0m3CC5aPf4b3p2WK--BW-4DJCOWzQ3TM0HQmiMqIFa4zAEicZv4iGMsw0D26JEBtS3NR656ywDpiYv869_11r-Ko12TQv0yLveI3eqfcjP111HUNVonrRTFuhdsVgAHWEAmuRxlG7SuEzKMi-yJAnhAjTLIk_EcbFJtuk2y9MphM8lM47KIp--AOZghtU\n\n### Impact\nXSS on all sites that use mermaid and render user supplied diagrams without further sanitization.\n\n### Remediation\nThe value of the `text` argument for the `calculateMathMLDimensions` method needs to be sanitized before getting passed on to `innerHTML`.",
  "id": "GHSA-7rqq-prvp-x9jh",
  "modified": "2025-08-22T22:52:04Z",
  "published": "2025-08-19T20:16:58Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/mermaid-js/mermaid/security/advisories/GHSA-7rqq-prvp-x9jh"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-54881"
    },
    {
      "type": "WEB",
      "url": "https://github.com/mermaid-js/mermaid/commit/5c69e5fdb004a6d0a2abe97e23d26e223a059832"
    },
    {
      "type": "WEB",
      "url": "https://github.com/mermaid-js/mermaid/commit/685516a85ec1df64cefd4fd15f26533be87d458e"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/mermaid-js/mermaid"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Mermaid improperly sanitizes sequence diagram labels leading to XSS"
}


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…