fix: mermaid graph (#29811)

Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com>
Co-authored-by: Joel <iamjoel007@gmail.com>
This commit is contained in:
-LAN-
2025-12-18 10:50:14 +08:00
committed by GitHub
parent 114f17f1ca
commit ae17537470
3 changed files with 86 additions and 11 deletions

View File

@@ -2,6 +2,28 @@ export function cleanUpSvgCode(svgCode: string): string {
return svgCode.replaceAll('<br>', '<br/>')
}
export const sanitizeMermaidCode = (mermaidCode: string): string => {
if (!mermaidCode || typeof mermaidCode !== 'string')
return ''
return mermaidCode
.split('\n')
.filter((line) => {
const trimmed = line.trimStart()
// Mermaid directives can override config; treat as untrusted in chat context.
if (trimmed.startsWith('%%{'))
return false
// Mermaid click directives can create JS callbacks/links inside rendered SVG.
if (trimmed.startsWith('click '))
return false
return true
})
.join('\n')
}
/**
* Prepares mermaid code for rendering by sanitizing common syntax issues.
* @param {string} mermaidCode - The mermaid code to prepare
@@ -12,10 +34,7 @@ export const prepareMermaidCode = (mermaidCode: string, style: 'classic' | 'hand
if (!mermaidCode || typeof mermaidCode !== 'string')
return ''
let code = mermaidCode.trim()
// Security: Sanitize against javascript: protocol in click events (XSS vector)
code = code.replace(/(\bclick\s+\w+\s+")javascript:[^"]*(")/g, '$1#$2')
let code = sanitizeMermaidCode(mermaidCode.trim())
// Convenience: Basic BR replacement. This is a common and safe operation.
code = code.replace(/<br\s*\/?>/g, '\n')