Feb 14, 2026·6 min read·36 visits
The `beautiful-mermaid` library, used to render Mermaid diagrams as SVGs, failed to sanitize user-supplied style attributes. Attackers can inject malicious payloads into `fill` or `stroke` properties, breaking out of the SVG XML structure to execute XSS. Fixed in version 0.1.3.
A critical flaw in the `beautiful-mermaid` library allows attackers to weaponize flowcharts and diagrams. By injecting malicious CSS strings into style definitions, adversaries can break out of SVG attributes and execute arbitrary JavaScript. This vulnerability transforms a harmless documentation tool into a vehicle for Cross-Site Scripting (XSS), affecting all versions prior to 0.1.3.
Mermaid diagrams are the darling of the developer documentation world. They turn cryptic text into beautiful flowcharts, sequence diagrams, and Gantt charts. The beautiful-mermaid library exists to take that text and render it into high-fidelity SVGs, perfect for embedding in websites or documentation portals. It promises "beautiful" rendering, but under the hood, it was doing something ugly: trusting user input blindly.
Imagine you are building a documentation platform. You allow users to submit Mermaid graphs to explain their microservices architecture. You render these server-side or client-side using beautiful-mermaid. It seems harmless enough—after all, it's just boxes and arrows, right? Wrong. In the security world, if you are building HTML or XML strings by mashing variables together without sanitization, you aren't building a renderer; you're building a vulnerability.
CVE-2026-26226 is the classic tale of convenience over security. The library treated style attributes like color, fill, and stroke as pure aesthetic choices, never expecting that someone might try to paint a box with a shade of " onload="alert(1). This oversight turns every diagram into a potential landmine for Cross-Site Scripting (XSS).
The root cause of this vulnerability is a fundamental misunderstanding of how to safely construct XML (and by extension, SVG) documents. There are two ways to build a DOM element: you can use a DOM API (like document.createElement), which naturally handles encoding, or you can build a massive string and hope for the best. beautiful-mermaid chose the latter.
In src/renderer.ts, the library parses the Mermaid syntax to extract node styles. If a user defines a specific style for a node—say, making it red—the library captures that string. The fatal error occurred when the library took those captured strings and interpolated them directly into a template literal to form the SVG output.
It didn't care what was in the string. It didn't look for quotes, angle brackets, or escape characters. It just pasted the value directly into the fill="..." attribute of the SVG string. This is the XML equivalent of SQL injection. The browser parser doesn't know that the attacker's double-quote meant "end of the attribute value." It just sees a closed attribute and a new, malicious instruction following immediately after.
Let's look at the crime scene in src/renderer.ts. The code was responsible for taking style properties and applying them to the SVG elements. Here is the vulnerable logic before the patch:
// Vulnerable: Direct interpolation of user input
const fill = inlineStyle?.fill ?? 'var(--_node-fill)'
const stroke = inlineStyle?.stroke ?? 'var(--_node-stroke)'
const sw = inlineStyle?.['stroke-width'] ?? String(STROKE_WIDTHS.innerBox)
// Later, this is used in a template literal:
// return `<rect fill="${fill}" stroke="${stroke}" ... />`If inlineStyle.fill is controlled by the user, they control the raw HTML output. The fix, introduced in version 0.1.3, is a textbook application of output encoding. The developers wrapped the tainted variables in an escapeXml function before interpolation:
// Fixed: Sanitizing the input before interpolation
const fill = escapeXml(inlineStyle?.fill ?? 'var(--_node-fill)')
const stroke = escapeXml(inlineStyle?.stroke ?? 'var(--_node-stroke)')
const sw = escapeXml(inlineStyle?.['stroke-width'] ?? String(STROKE_WIDTHS.innerBox))This simple change ensures that a double quote " becomes ", preventing the attacker from breaking out of the attribute context. It converts a weaponized string back into a harmless (albeit likely invalid) color value.
Exploiting this is trivially easy once you understand the underlying string concatenation. We don't need complex memory corruption or race conditions; we just need to balance some quotes. The attack vector typically involves the style directive in Mermaid syntax, which allows applying CSS to specific nodes.
Scenario 1: The Event Handler Injection
We want to inject onmouseover="alert(1)". The target code looks roughly like <rect fill="${USER_INPUT}" ... />. If we set our fill color to red" onmouseover="alert(1), the rendered SVG becomes:
<rect fill="red" onmouseover="alert(1)" ... />The browser sees a red rectangle that executes JavaScript when you hover over it.
The Payload:
Scenario 2: The Element Injection
If we want to be louder, we can close the rect tag entirely and start a new script tag. We set the fill to red"/><script>alert(origin)</script><rect fill="x.
The Payload:
This results in a valid SVG structure that includes an inline script block, executing immediately upon rendering in many contexts (though modern CSPs might block inline scripts, the event handler vector remains potent).
While the CVSS score is a moderate 5.3 (primarily because user interaction is usually required to view the diagram, and the scope is limited to the browser), the practical impact can be severe depending on the implementation. This is a classic stored XSS vector.
If a developer uses beautiful-mermaid to render user-generated content (like comments, wiki pages, or issue trackers) server-side and serves the resulting SVG, they are serving weaponized content. SVGs are powerful; they are essentially XML documents that can contain scripts, external object references, and more.
Successful exploitation means an attacker can:
Since this library is likely used in documentation tools or dashboards, the victims are often privileged users (developers, admins) viewing internal diagrams, making the target value high.
The remediation is straightforward: stop trusting strings. The maintainers of beautiful-mermaid released version 0.1.3 which includes the necessary escaping logic. If you are using this library, you need to upgrade immediately.
> [!TIP]
> Action Item: Run npm list beautiful-mermaid or bun pm ls to check your version. If it is < 0.1.3, update it.
If you cannot update for some reason (perhaps you enjoy living on the edge), you must implement a strict Content Security Policy (CSP). A CSP that forbids unsafe-inline scripts and restricts object-src can mitigate the impact of the XSS, preventing the execution of the injected JavaScript even if the HTML is malformed.
However, the only true fix is the patch. Sanitization is hard; don't try to write your own regex to strip quotes. Use the vendor's fix which properly encodes XML entities.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:L/VI:L/VA:N/SC:L/SI:L/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
beautiful-mermaid lukilabs | < 0.1.3 | 0.1.3 |
| Attribute | Detail |
|---|---|
| CWE | CWE-79 (XSS) |
| CVSS v4.0 | 5.3 (Medium) |
| Attack Vector | Network (Payload delivery) |
| Privileges Required | None |
| User Interaction | Passive (Viewing diagram) |
| Exploit Status | PoC Available |
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
CVE-2026-49851 is a high-severity algorithmic complexity vulnerability in the Mistune Markdown parser. Under specific conditions involving dense, unmatched nesting of opening square brackets, the parser fallback loops degrade from linear execution time to a worst-case quadratic complexity. This allows unauthenticated remote attackers to trigger complete CPU exhaustion and subsequent Denial of Service with a highly compact payload.
An allocation of resources without limits or throttling vulnerability in the Elixir Mint HTTP client library allows malicious HTTP/2 servers to trigger memory exhaustion and application denial of service. The flaw exists because Mint fails to validate server-push concurrency limits during the receipt of PUSH_PROMISE frames, deferring validation to the HEADERS phase. This allows a server to reserve an unlimited number of streams in the client's memory map.
An unsafe execution vulnerability exists in the Bazar form field calculator (CalcField.php) of YesWiki prior to version 4.6.6. The application attempts to validate mathematical formulas using a complex recursive regular expression before passing them to the PHP eval() function. This design leads to both Regular Expression Denial of Service (ReDoS) and Remote Code Execution (RCE) via validation bypass.
An infinite loop vulnerability exists in the pure-Python PDF library pypdf prior to version 6.13.1. When parsing or merging a crafted PDF file containing a cyclic Article/Thread structure, the library fails to exit its traversal loop. This causes the executing thread to hang indefinitely, leading to 100% CPU utilization and a denial of service. The vulnerability is tracked under CVE-2026-54651 and GHSA-g9xf-7f8q-9mcj, with a CVSS base score of 5.5. This technical report provides a root cause analysis, code review, exploitation vectors, and mitigation paths.
The Netty-based HTTP Client in the Micronaut framework fails to enforce a maximum redirect ceiling by default when processing HTTP responses. This permits remote, attacker-controlled servers to trigger continuous, infinite redirect loops. The resulting recursion causes high CPU utilization, thread starvation, and potential memory exhaustion, inducing a Denial of Service (DoS) state in client-side applications.
An information disclosure vulnerability exists in the Micronaut Framework's HTTP client components. The client fails to clear sensitive authorization headers and cookies when following redirects across different origins. If an application using the vulnerable client communicates with an endpoint that issues a redirect to an external host, the client will forward the original credentials, leading to potential token theft and session hijacking.