ghsa-8gwm-58g9-j8pw
Vulnerability from github
Summary
In the default configuration of mermaid 11.9.0, user supplied input for architecture diagram icons is passed to the d3 html() method, creating a sink for cross site scripting.
Details
Architecture diagram service iconText values are passed to the d3 html() method, allowing malicious users to inject arbitrary HTML and cause XSS when mermaid-js is used in it's default configuration.
The vulnerability lies here:
ts
export const drawServices = async function (
db: ArchitectureDB,
elem: D3Element,
services: ArchitectureService[]
): Promise<number> {
for (const service of services) {
/** ... **/
} else if (service.iconText) {
bkgElem.html(
`<g>${await getIconSVG('blank', { height: iconSize, width: iconSize, fallbackPrefix: architectureIcons.prefix })}</g>`
);
const textElemContainer = bkgElem.append('g');
const fo = textElemContainer
.append('foreignObject')
.attr('width', iconSize)
.attr('height', iconSize);
const divElem = fo
.append('div')
.attr('class', 'node-icon-text')
.attr('style', `height: ${iconSize}px;`)
.append('div')
.html(service.iconText); // <- iconText passed into innerHTML
/** ... **/
};
};
This issue was introduced with 734bde38777c9190a5a72e96421c83424442d4e4, around 15 months ago, which was released in v11.1.0.
PoC
Render the following diagram and observe the modified DOM.
architecture-beta
group api(cloud)[API]
service db "<img src=x onerror=\"document.write(`xss on ${document.domain}`)\">" [Database] in api
Here is a PoC on mermaid.live: https://mermaid.live/edit#pako:eNo9T8FOwzAM_ZXI4rBJpWrpRtuIISF24caZZdKyxOsiLUnlJjCo-u9kQ8wX-_n5-dkjKK8ROEhSRxNQhUh4v8cghWMpOvKxZ7I3M3XyUc83L-9v2z9qQPo0CpneMwFPxnZsILU6M--QyNNKCAHaq2jRhfyL0vLZ7jwMiWd3443Q3krjpt38Mv4sgG3WMsi9HHDLjLs4CwcZdGQ08EARM7BISZMgjJdLBIQjWhTAU6nxIOMpCBBuSrJeug_v7b8yPdMdgR_kaUgo9loGXBvZkbS3LqHTSK8-ugC8LMrrEuAjnIEvlnlVL9q6rZu6Lh-rRQbfwKuyyZuybcvqIaWiqKcMfq6uRd7Uy-kXhYFzcA
Impact
XSS on all sites that use mermaid and render user supplied diagrams without further sanitization.
Remediation
Sanitize the value of iconText before passing it to html().
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "mermaid"
},
"ranges": [
{
"events": [
{
"introduced": "11.1.0"
},
{
"fixed": "11.10.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-54880"
],
"database_specific": {
"cwe_ids": [
"CWE-79"
],
"github_reviewed": true,
"github_reviewed_at": "2025-08-19T20:16:45Z",
"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 architecture diagram icons is passed to the d3 `html()` method, creating a sink for cross site scripting.\n\n### Details\nArchitecture diagram service `iconText` values are passed to the d3 `html()` method, allowing malicious users to inject arbitrary HTML and cause XSS when mermaid-js is used in it\u0027s default configuration. \n\nThe vulnerability lies here:\n\n```ts\nexport const drawServices = async function (\n db: ArchitectureDB,\n elem: D3Element,\n services: ArchitectureService[]\n): Promise\u003cnumber\u003e {\n for (const service of services) {\n /** ... **/\n } else if (service.iconText) {\n bkgElem.html(\n `\u003cg\u003e${await getIconSVG(\u0027blank\u0027, { height: iconSize, width: iconSize, fallbackPrefix: architectureIcons.prefix })}\u003c/g\u003e`\n );\n const textElemContainer = bkgElem.append(\u0027g\u0027);\n const fo = textElemContainer\n .append(\u0027foreignObject\u0027)\n .attr(\u0027width\u0027, iconSize)\n .attr(\u0027height\u0027, iconSize);\n const divElem = fo\n .append(\u0027div\u0027)\n .attr(\u0027class\u0027, \u0027node-icon-text\u0027)\n .attr(\u0027style\u0027, `height: ${iconSize}px;`)\n .append(\u0027div\u0027)\n .html(service.iconText); // \u003c- iconText passed into innerHTML\n /** ... **/\n};\n};\n```\n\nThis issue was introduced with 734bde38777c9190a5a72e96421c83424442d4e4, around 15 months ago, which was released in [v11.1.0](https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.1.0).\n\n### PoC\nRender the following diagram and observe the modified DOM.\n\n```\narchitecture-beta\n group api(cloud)[API]\n service db \"\u003cimg src=x onerror=\\\"document.write(`xss on ${document.domain}`)\\\"\u003e\" [Database] in api\n```\n\nHere is a PoC on mermaid.live: https://mermaid.live/edit#pako:eNo9T8FOwzAM_ZXI4rBJpWrpRtuIISF24caZZdKyxOsiLUnlJjCo-u9kQ8wX-_n5-dkjKK8ROEhSRxNQhUh4v8cghWMpOvKxZ7I3M3XyUc83L-9v2z9qQPo0CpneMwFPxnZsILU6M--QyNNKCAHaq2jRhfyL0vLZ7jwMiWd3443Q3krjpt38Mv4sgG3WMsi9HHDLjLs4CwcZdGQ08EARM7BISZMgjJdLBIQjWhTAU6nxIOMpCBBuSrJeug_v7b8yPdMdgR_kaUgo9loGXBvZkbS3LqHTSK8-ugC8LMrrEuAjnIEvlnlVL9q6rZu6Lh-rRQbfwKuyyZuybcvqIaWiqKcMfq6uRd7Uy-kXhYFzcA\n\n### Impact\nXSS on all sites that use mermaid and render user supplied diagrams without further sanitization.\n\n### Remediation\nSanitize the value of `iconText` before passing it to `html()`.",
"id": "GHSA-8gwm-58g9-j8pw",
"modified": "2025-08-20T19:13:27Z",
"published": "2025-08-19T20:16:45Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/mermaid-js/mermaid/security/advisories/GHSA-8gwm-58g9-j8pw"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-54880"
},
{
"type": "WEB",
"url": "https://github.com/mermaid-js/mermaid/commit/2aa83302795183ea5c65caec3da1edd6cb4791fc"
},
{
"type": "WEB",
"url": "https://github.com/mermaid-js/mermaid/commit/734bde38777c9190a5a72e96421c83424442d4e4"
},
{
"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:L/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Mermaid does not properly sanitize architecture diagram iconText leading to XSS"
}
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.