Summary
The SanitizeSVG function introduced in v3.6.0 to fix XSS in the unauthenticated /api/icon/getDynamicIcon endpoint can be bypassed by using namespace-prefixed element names such as <x:script xmlns:x="http://www.w3.org/2000/svg">. The Go HTML5 parser records the element's tag as "x:script" rather than "script", so the tag check passes it through. The SVG is served with Content-Type: image/svg+xml and no Content Security Policy; when a browser opens the response directly, its XML parser resolves the prefix to the SVG namespace and executes the embedded script.
Details
The getDynamicIcon route is registered without authentication:
// kernel/server/serve.go
ginServer.Handle("GET", "/api/icon/getDynamicIcon", getDynamicIcon)
For type 8, the content query parameter is inserted directly into an SVG <text> element using fmt.Sprintf with no HTML encoding:
// kernel/api/icon.go:579-584
return fmt.Sprintf(`
<svg id="dynamic_icon_type8" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path d="..."/>
<text x="50%%" y="55%%" ...>%s</text>
</svg>`, ..., content)
SanitizeSVG then parses the SVG with github.com/88250/lute/html and removes elements whose lowercased tag name matches a fixed list:
// kernel/util/misc.go:249-252
tag := strings.ToLower(c.Data)
if tag == "script" || tag == "iframe" || tag == "object" || tag == "embed" ||
tag == "foreignobject" || "animate" == tag || ... {
n.RemoveChild(c)
The lute HTML parser stores the full qualified name including any namespace prefix in Node.Data. A payload like <x:script xmlns:x="http://www.w3.org/2000/svg"> gets Data = "x:script". The check tag == "script" is false, so the element is not removed and survives in the rendered output.
Confirmed with the same library version used by SiYuan:
html.Parse input: <x:script xmlns:x="http://www.w3.org/2000/svg">alert(1)</x:script>
Node.Data result: "x:script" (not "script")
Removed by check: false
Rendered output: <x:script xmlns:x="http://www.w3.org/2000/svg">alert(1)</x:script>
The same bypass works for every element on the blocklist: x:iframe, x:object, x:foreignObject, etc.
The fix is to strip the namespace prefix before comparing:
localName := tag
if i := strings.LastIndex(tag, ":"); i >= 0 {
localName = tag[i+1:]
}
if localName == "script" || localName == "iframe" || ...
PoC
GET /api/icon/getDynamicIcon?type=8&color=red&content=%3C%2Ftext%3E%3Cx%3Ascript%20xmlns%3Ax%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3Ealert%28document.domain%29%3C%2Fx%3Ascript%3E%3Ctext%3E HTTP/1.1
Host: 127.0.0.1:6806
Decoded content value:
</text><x:script xmlns:x="http://www.w3.org/2000/svg">alert(document.domain)</x:script><text>
The response is a valid SVG with the script element intact. Opening the URL directly in a browser triggers the alert, confirming script execution at the SiYuan server origin.
Impact
Any user whose SiYuan instance is reachable over a local network is exposed. An attacker on the same network can craft the URL and share it. When the victim opens it in a browser, JavaScript executes at the http://<siyuan-host>:6806 origin. Because SiYuan sets Access-Control-Allow-Origin: * and the script runs same-origin, it can call any API endpoint using the victim's existing session cookies, including endpoints to read all notes, export data, or modify settings. No authentication or prior access is needed to construct the payload.
Untrusted input is rendered as active markup in a victim's browser, which can run script in their session. Typical impact: session or credential theft, and actions taken as the user.
CVE-2026-34605 has a CVSS score of 6.1 (High). The vector is network-reachable, no privileges required, and user interaction required. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (0.0.0-20260330031106-f09953afc57a); upgrading removes the vulnerable code path.
Affected versions
Security releases
Kodem intelligence
Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.
Remediation advice
Kodem Kai can prioritize this vulnerability in your dependency tree and generate a fix recommendation.
Frequently Asked Questions
- What is CVE-2026-34605? CVE-2026-34605 is a high-severity cross-site scripting (XSS) vulnerability in github.com/siyuan-note/siyuan/kernel (go), affecting versions < 0.0.0-20260330031106-f09953afc57a. It is fixed in 0.0.0-20260330031106-f09953afc57a. Untrusted input is rendered as active markup in a victim's browser, which can run script in their session.
- How severe is CVE-2026-34605? CVE-2026-34605 has a CVSS score of 6.1 (High). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
- Which versions of github.com/siyuan-note/siyuan/kernel are affected by CVE-2026-34605? github.com/siyuan-note/siyuan/kernel (go) versions < 0.0.0-20260330031106-f09953afc57a is affected.
- Is there a fix for CVE-2026-34605? Yes. CVE-2026-34605 is fixed in 0.0.0-20260330031106-f09953afc57a. Upgrade to this version or later.
- Is CVE-2026-34605 exploitable, and should I be worried? Whether CVE-2026-34605 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
- What actually determines whether CVE-2026-34605 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
- How do I fix CVE-2026-34605? Upgrade
github.com/siyuan-note/siyuan/kernelto 0.0.0-20260330031106-f09953afc57a or later.