highCVSS 8.7Vulnerability

GHSA-99rq-75j6-5j9f

### Summary SiYuan cleans user supplied SVG with `util.SanitizeSVG` before it serves the file inline as `image/svg+xml`. This cleaner is the guard behind the `Editor.AllowSVGScript` setting, which is off by default, so a `<script>` inside an SVG is meant to be removed. The cleaner reads the input as HTML, but the browser reads the served file as XML (SVG). Because the two parsers treat some tags differently, a `<script>` can be hidden so the cleaner never removes it. The cleaned file still holds a working script. When a browser opens that file as an SVG document, the script runs in the app origin. There is no Content Security Policy in the product to stop it. The same bug can be reached in two ways. Both share one root cause (the cleaner), so one fix in the cleaner closes both: * Reflected, through a single link: `GET /api/icon/getDynamicIcon` * Stored, through a planted `.svg` asset: `GET /assets/<name>.svg` I confirmed this on a live SiYuan 3.7.2 kernel. ## Root cause `util.SanitizeSVG` (`kernel/util/misc.go:319`) parses the string with an HTML parser, walks the element nodes to drop `<script>`, `<iframe>`, `<foreignobject>`, event handler attributes and so on, then renders it back and cuts out the `<svg>...</svg>` part. The gap comes from HTML parsing rules that do not exist in XML: * `<desc>` and `<title>` are HTML integration points. Inside them the HTML parser switches back to normal HTML mode. The cleaner drops `<foreignObject>` but keeps `<desc>` and `<title>`. * Inside HTML mode, `<style>`, `<xmp>` and `<noscript>` are raw text elements. Their contents are read as plain text, not as child nodes. So the cleaner never sees a `<script>` placed inside them, and the render step writes it back exactly as it was. * When the browser reads the same bytes as XML (SVG), there is no raw text rule. `<style>` becomes a normal container and the hidden `<script>` becomes a real, working SVG script node. I checked this by building and running the real `SanitizeSVG`

Properties

ghsa_id
GHSA-99rq-75j6-5j9f
severity
high
summary
SiYuan: Stored and reflected XSS in SiYuan through an SVG sanitizer bypass
cvss_score
8.7
cve_id
GHSA-99rq-75j6-5j9f
cvss_vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N
is_ghsa_only
true
ghsa_published
2026-09-03T14:53:17Z
source_url
https://github.com/advisories/GHSA-99rq-75j6-5j9f
ghsa_updated
2026-09-03T14:53:18Z

Related Entities (4)

VULNERABLE_TO (1)

[Software]go/github.com/siyuan-note/siyuan/kernel

AFFECTS (1)

[Software]go/github.com/siyuan-note/siyuan/kernel

HAS_WEAKNESS (1)

[Weakness]Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

REPORTED_BY (1)

[Source]GitHub Advisory Database

Explore deeper with Ninja Signal's threat intelligence graph

GHSA-99rq-75j6-5j9f (CVSS 8.7) — Ninja Signal Threat Intelligence | Ninja Signal