Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions en/docs/assets/js/mermaid-init.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
document.addEventListener("DOMContentLoaded", function () {
// Select all .mermaid elements
const mermaidElements = document.querySelectorAll(".mermaid");

mermaidElements.forEach((el) => {
// 1. Extract content from <code> tag if it exists, otherwise use el.innerHTML
const codeTag = el.querySelector("code");
let content = codeTag ? codeTag.innerHTML : el.innerHTML;

// 2. Decode HTML entities (e.g., &gt; to >)
content = content
.replace(/&lt;/g, "<")
.replace(/&gt;/g, ">")
.replace(/&amp;/g, "&")
.replace(/&quot;/g, '"');

// 3. Update the element's textContent with the clean, decoded content
// We use textContent to ensure no HTML tags remain.
el.textContent = content.trim();
});

// 4. Initialize mermaid now that the content is clean
mermaid.initialize({
startOnLoad: true,
theme: document.body.getAttribute("data-md-color-scheme") === "slate" ? "dark" : "default",
securityLevel: "loose",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In Mermaid 10.6.1, what are the security differences between securityLevel "strict", "antiscript", and "loose", and which is recommended for untrusted markdown/diagram content?

💡 Result:

In Mermaid 10.6.1, securityLevel primarily controls (a) whether Mermaid will allow raw HTML in diagram text/labels and (b) whether click interactions (e.g., click directives) are enabled:

  • "strict" (default): HTML tags in text are encoded/escaped, and click functionality is disabled. This is the safest of the three. [1]
  • "antiscript": HTML tags in text are allowed, but Mermaid removes only <script> elements; click functionality is enabled. This still leaves a much larger XSS/abuse surface than strict (because it allows HTML and interactivity). [1]
  • "loose": HTML tags in text are allowed, and click functionality is enabled—the least restrictive / highest risk option. [1]

Recommendation for untrusted markdown/diagram content: use securityLevel: "strict" (and do not enable loose/antiscript for untrusted user input). [1][2]

Sources:
[1] Mermaid config schema docs (securityLevel) https://mermaid.js.org/config/schema-docs/config-properties-securitylevel.html
[2] Example of risk when securityLevel: "loose" enables clickable JS execution paths (advisory write-up) https://dbugs.ptsecurity.com/vulnerability/PT-2026-25086


🏁 Script executed:

# Check the actual file content and context around line 26
cat -n en/docs/assets/js/mermaid-init.js | head -40

Repository: wso2/docs-bi

Length of output: 1452


🏁 Script executed:

# Check for Mermaid version specification in package.json or similar
fd -type f \( -name "package.json" -o -name "requirements.txt" -o -name "Gemfile" -o -name ".nvmrc" \) | head -10 | xargs cat

Repository: wso2/docs-bi

Length of output: 226


🏁 Script executed:

# Search for other mermaid configuration in the codebase
rg -i "mermaid|securityLevel" --type js --type json --type html --type md -B 2 -A 2 | head -100

Repository: wso2/docs-bi

Length of output: 3473


Change securityLevel: "loose" to securityLevel: "strict" for documentation that accepts external contributions.

Line 26 weakens Mermaid's security model. The "loose" setting allows HTML tags in diagram text and enables click interactions, creating an XSS exposure risk for diagrams contributed via PRs or other external sources. The preprocessing in lines 5–20 only normalizes initial content and does not prevent Mermaid's rendering rules from interpreting malicious input.

Mermaid's "strict" mode (the default) escapes HTML and disables click functionality, making it the recommended setting for untrusted markdown/diagram content.

Safer default
-        securityLevel: "loose",
+        securityLevel: "strict",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@en/docs/assets/js/mermaid-init.js` at line 26, The Mermaid initialization
sets securityLevel: "loose", which allows HTML and click interactions and is
unsafe for external contributions; update the Mermaid config in mermaid-init.js
to set securityLevel: "strict" (replace the "loose" value with "strict" in the
config object where securityLevel is defined) so HTML is escaped and click
functionality is disabled for untrusted diagram inputs.

});

// 5. Manually trigger rendering in case startOnLoad doesn't pick up the changes
mermaid.run();
Comment on lines +23 to +30
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify current implementation has no mermaid availability guard
rg -n 'mermaid\.initialize|mermaid\.run|typeof\s+window\.mermaid|typeof\s+mermaid' en/docs/assets/js/mermaid-init.js

# Verify Mermaid runtime is externally loaded from CDN
rg -n 'extra_javascript|mermaid-init\.js|mermaid\.min\.js|unpkg\.com/mermaid' en/mkdocs.yml -C2

Repository: wso2/docs-bi

Length of output: 515


Fix Mermaid initialization: add runtime guard AND fix script loading order.

Lines 23 and 30 call mermaid.initialize() and mermaid.run() without guards, but more critically, en/mkdocs.yml loads mermaid-init.js (line 269) before the Mermaid library itself (line 270). This causes mermaid to be undefined when the initialization script executes, failing on every page load.

Two fixes required:

  1. Add a runtime guard in the initialization script
  2. Reorder mkdocs.yml to load the Mermaid library before the initialization script
Proposed fixes

In en/docs/assets/js/mermaid-init.js:

-    mermaid.initialize({
+    if (typeof window.mermaid === "undefined") {
+        console.error("Mermaid runtime is not available; diagrams were not rendered.");
+        return;
+    }
+
+    window.mermaid.initialize({
         startOnLoad: true,
         theme: document.body.getAttribute("data-md-color-scheme") === "slate" ? "dark" : "default",
         securityLevel: "loose",
     });

-    mermaid.run();
+    window.mermaid.run();

In en/mkdocs.yml:

 extra_javascript:
     - assets/lib/json-formatter/json-formatter.umd.js
     - assets/lib/highlightjs/highlight.min.js
     - assets/js/theme.js
     - assets/js/copy-page.js
-    - assets/js/mermaid-init.js
     - https://unpkg.com/mermaid@10.6.1/dist/mermaid.min.js
+    - assets/js/mermaid-init.js
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
mermaid.initialize({
startOnLoad: true,
theme: document.body.getAttribute("data-md-color-scheme") === "slate" ? "dark" : "default",
securityLevel: "loose",
});
// 5. Manually trigger rendering in case startOnLoad doesn't pick up the changes
mermaid.run();
if (typeof window.mermaid === "undefined") {
console.error("Mermaid runtime is not available; diagrams were not rendered.");
return;
}
window.mermaid.initialize({
startOnLoad: true,
theme: document.body.getAttribute("data-md-color-scheme") === "slate" ? "dark" : "default",
securityLevel: "loose",
});
// 5. Manually trigger rendering in case startOnLoad doesn't pick up the changes
window.mermaid.run();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@en/docs/assets/js/mermaid-init.js` around lines 23 - 30, The initialization
script mermaid-init.js calls mermaid.initialize() and mermaid.run() without
checking that the global mermaid object exists and mkdocs.yml currently loads
mermaid-init.js before the Mermaid library; fix by adding a runtime guard in
mermaid-init.js that checks for window.mermaid (or typeof mermaid !==
"undefined") and only calls mermaid.initialize(...) and mermaid.run() when
present (optionally retry/late-init if absent), and update en/mkdocs.yml to load
the Mermaid library entry before the mermaid-init.js entry so the library is
available when mermaid-init.js executes.

});
Loading