SiYuan has a SanitizeSVG bypass via data:text/xml in getDynamicIcon (incomplete fix for CVE-2026-29183)
Date: 2026-03
Affected: go/github.com/siyuan-note/siyuan
Attack vector: xss
Category: vulnerability-disclosure
Severity: Critical
CVE: CVE-2026-29183
CVE-2026-32747
CVE-2026-32751
CVE-2026-32767
CVE-2026-32815
CVE-2026-32938
CVE-2026-32940
CWE: CWE-184
CWE-200
CWE-22
CWE-284
CWE-287
CWE-79
CWE-863
CWE-89
CVSS: 9.3 (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N)

# SanitizeSVG bypass via data:text/xml in getDynamicIcon (incomplete fix for CVE-2026-29183) `SanitizeSVG` blocks `data:text/html` and `data:image/svg+xml` in href attributes but misses `data:text/xml` and `data:application/xml`. Both render SVG with `onload` JavaScript execution (confirmed in Chromium 136, other browsers untested). `/api/icon/getDynamicIcon` is unauthenticated and serves SVG as `Content-Type: image/svg+xml`. The `content` parameter (type=8) gets embedded into the SVG via `fmt.Sprintf` with no escaping. The sanitizer catches `data:text/html` but `data:text/xml` passes the blocklist -- only three MIME types are checked. This is a click-through XSS: victim visits the crafted URL, sees an SVG with an injected link, clicks it. If SiYuan renders these icons via `<img>` tags in the frontend, links aren't interactive there -- the attack needs direct navigation to the endpoint URL or `<object>`/`<embed>` embedding. ## Steps to reproduce Against SiYuan v3.6.0 (Docker): ```sh # 1. data:text/xml bypass -- <a> element preserved with href intact curl -s --get "http://127.0.0.1:6806/api/icon/getDynamicIcon" \ --data-urlencode 'type=8' \ --data-urlencode 'content=</text><a href="data:text/xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 onload=%27alert(document.domain)%27/%3E">click</a><text>' \ | grep -o '<a [^>]*>' # Output: <a href="data:text/xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 onload=%27alert(document.domain)%27/%3E"> # 2. data:text/html is c


Mitigations:

Architectural layers (MAESTRO):