SiYuan: Unauthenticated reflected SVG XSS in `/api/icon/getDynamicIcon` (`type=8`) enables arbitrary JavaScript execution
Description
SiYuan is a personal knowledge management system. Prior to version 3.5.9, an unauthenticated reflected XSS vulnerability exists in the dynamic icon API endpoint "GET /api/icon/getDynamicIcon" when type=8, attacker-controlled content is embedded into SVG output without escaping. Because the endpoint is unauthenticated and returns image/svg+xml, a crafted URL can inject executable SVG/HTML event handlers (for example onerror) and run JavaScript in the SiYuan web origin. This can be chained to perform authenticated API actions and exfiltrate sensitive data when a logged-in user opens the malicious link. This issue has been patched in version 3.5.9.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/siyuan-note/siyuan/kernelGo | < 0.0.0-20260304034809-d68bd5a79391 | 0.0.0-20260304034809-d68bd5a79391 |
Affected products
1- Range: < 3.5.9
Patches
1d68bd5a79391:lock: https://github.com/siyuan-note/siyuan/security/advisories/GHSA-6865-qjcf-286f
3 files changed · +56 −9
kernel/api/icon.go+1 −1 modified@@ -165,7 +165,7 @@ func getDynamicIcon(c *gin.Context) { } if !model.Conf.Editor.AllowSVGScript { - svg = util.RemoveScriptsInSVG(svg) + svg = util.SanitizeSVG(svg) } c.Header("Content-Type", "image/svg+xml")
kernel/server/serve.go+1 −1 modified@@ -618,7 +618,7 @@ func serveSVG(context *gin.Context, assetAbsPath string) bool { } if !model.Conf.Editor.AllowSVGScript { - data = []byte(util.RemoveScriptsInSVG(string(data))) + data = []byte(util.SanitizeSVG(string(data))) } context.Data(200, "image/svg+xml", data)
kernel/util/misc.go+54 −7 modified@@ -231,8 +231,7 @@ func ReplaceStr(strs []string, old, new string) (ret []string, changed bool) { return } -// RemoveScriptsInSVG 移除 SVG 中的 <script> 标签及其内部所有内容 -func RemoveScriptsInSVG(svgInput string) string { +func SanitizeSVG(svgInput string) string { // 1. 将字符串解析为节点树 doc, err := html.Parse(strings.NewReader(svgInput)) if err != nil { @@ -246,13 +245,61 @@ func RemoveScriptsInSVG(svgInput string) string { // 倒序遍历子节点,确保删除操作不影响后续迭代 for c := n.FirstChild; c != nil; { next := c.NextSibling - // 检查标签名是否为 script - if c.Type == html.ElementNode && strings.EqualFold(c.Data, "script") { - n.RemoveChild(c) - } else { - // 递归处理子节点 + if c.Type == html.ElementNode { + tag := strings.ToLower(c.Data) + if tag == "script" || tag == "iframe" || tag == "object" || tag == "embed" || tag == "foreignobject" { + n.RemoveChild(c) + c = next + continue + } + + // 清理不安全属性 + if len(c.Attr) > 0 { + // 过滤属性:删除以 on 开头的属性(事件处理),href/xlink:href 指向 javascript: 或不安全 data:,以及危险的 style 表达式 + filtered := c.Attr[:0] + for _, a := range c.Attr { + key := strings.ToLower(a.Key) + val := strings.TrimSpace(strings.ToLower(a.Val)) + + // 删除事件处理器属性(onload, onerror 等) + if strings.HasPrefix(key, "on") { + continue + } + + // 删除 href 或 xlink:href 指向 javascript: 或某些不安全的 data: URI + if key == "href" || key == "xlink:href" || key == "xlinkhref" { + if strings.HasPrefix(val, "javascript:") { + continue + } + // 对 data: 做保守处理,删除包含可执行内容的 data:text/html 或 data:image/svg+xml + if strings.HasPrefix(val, "data:") { + if strings.Contains(val, "text/html") || strings.Contains(val, "image/svg+xml") || strings.Contains(val, "application/xhtml+xml") { + continue + } + } + } + + // 清理 style 中的危险表达式,如 expression() 或 url(javascript:...) + if key == "style" { + low := val + if strings.Contains(low, "expression(") || strings.Contains(low, "url(javascript:") || strings.Contains(low, "javascript:") { + // 丢弃整个 style 属性以保证安全 + continue + } + } + + // 其它属性保留 + filtered = append(filtered, a) + } + c.Attr = filtered + } + } + + // 递归处理子节点(如果节点尚未被删除) + if c.Parent != nil { walk(c) } + c = next } }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-6865-qjcf-286fghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-29183ghsaADVISORY
- github.com/siyuan-note/siyuan/commit/d68bd5a79391742b3cb2e14d892bdd9997064927ghsaWEB
- github.com/siyuan-note/siyuan/security/advisories/GHSA-6865-qjcf-286fghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.