CVE-2026-31807: Github.com/siyuan note/siyuan/kernel Cross-Site Scripting Vulnerability

MODERATE
Advisory Identifier: GHSA-5hc8-qmg8-pw27
CWE-79
Published
Advisory Summary

CVE-2026-31807 is a MODERATE cross-site scripting vulnerability (CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')) affecting Github.com/siyuan note/siyuan/kernel libraries in the Go ecosystem. The issue involves siyuan has a svg sanitizer bypass via `<animate>` element — unauthenticated xss. Remediation is available by upgrading affected packages to version 0.0.0-20260310025236-297bd526708f.

CVE-2026-31807 at a Glance

CVE Identifier CVE-2026-31807
GHSA Identifier GHSA-5hc8-qmg8-pw27
Severity MODERATE
CVSS v3.1 Base Score N/A
CWE Classification CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
Affected Product Github.com/siyuan note/siyuan/kernel
Package Ecosystem Go
Published Date
Last Updated

How to Fix CVE-2026-31807

To remediate this vulnerability, upgrade all affected Github.com/siyuan note/siyuan/kernel dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

github.com/siyuan-note/siyuan/kernel fixed: 0.0.0-20260310025236-297bd526708f
Upgrade github.com/siyuan-note/siyuan/kernel to 0.0.0-20260310025236-297bd526708f
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for github.com/siyuan-note/siyuan/kernel

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-31807, inspect your project dependencies for Github.com/siyuan note/siyuan/kernel:

inspect dependencies for github.com/siyuan-note/siyuan/kernel

Analyze the terminal output to locate any version of Github.com/siyuan note/siyuan/kernel in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.0.0-20260310025236-297bd526708f), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting'), where the product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users. In Github.com/siyuan note/siyuan/kernel, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

# 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.

CVE-2026-31807 Affected Github.com/siyuan note/siyuan/kernel Versions

1 component(s)
Fixed Versions:
0.0.0-20260310025236-297bd526708f
Product / Package Ecosystem Affected Versions Fixed Version
github.com/siyuan-note/siyuan/kernel
Go
< 0.0.0-20260310025236-297bd526708f
0.0.0-20260310025236-297bd526708f

References

Frequently Asked Questions

What is CVE-2026-31807?
CVE-2026-31807 is a security vulnerability in Github.com/siyuan note/siyuan/kernel involving SiYuan has a SVG Sanitizer Bypass via `<animate>` Element — Unauthenticated XSS under CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting').
Which Github.com/siyuan note/siyuan/kernel versions are affected?
Affected versions include releases prior to 0.0.0-20260310025236-297bd526708f across affected packages: github.com/siyuan-note/siyuan/kernel.
What version fixes CVE-2026-31807?
Upgrading to 0.0.0-20260310025236-297bd526708f (or the latest patched release for your respective branch) resolves the vulnerability.
Is github.com/siyuan-note/siyuan/kernel affected?
Yes, github.com/siyuan-note/siyuan/kernel is affected in releases prior to 0.0.0-20260310025236-297bd526708f. Upgrade your dependency to 0.0.0-20260310025236-297bd526708f or later.
What CWE is associated with CVE-2026-31807?
CVE-2026-31807 is classified under CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.).
How can I check Go dependencies for CVE-2026-31807?
Run the dependency tree command: 'inspect dependencies for github.com/siyuan-note/siyuan/kernel'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-5hc8-qmg8-pw27",
  "modified" : "2026-03-10T23:49:23Z",
  "published" : "2026-03-10T23:49:23Z",
  "aliases" : [ "CVE-2026-31807" ],
  "summary" : "SiYuan has a SVG Sanitizer Bypass via `<animate>` Element — Unauthenticated XSS",
  "details" : "# SVG Sanitizer Bypass via `<animate>` Element — Unauthenticated XSS\n\n## Summary\n\nSiYuan'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.\n\nThis is a bypass of the fix for CVE-2026-29183 (fixed in v3.5.9).\n\n## Affected Component\n\n- **File:** `kernel/util/misc.go`\n- **Function:** `SanitizeSVG()` (lines 234-319)\n- **Endpoint:** `GET /api/icon/getDynamicIcon?type=8&content=...` (unauthenticated)\n- **Version:** SiYuan <= 3.5.9\n\n## Root Cause\n\nThe 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.\n\n### Sanitizer's blocklist (line 250)\n\n```go\nif tag == \"script\" || tag == \"iframe\" || tag == \"object\" || tag == \"embed\" || tag == \"foreignobject\" {\n    n.RemoveChild(c)\n    // ...\n}\n```\n\nMissing from blocklist: `animate`, `set`, `animateTransform`, `animateMotion`\n\n### Attribute check (lines 264-267)\n\n```go\n// Only checks static attributes\nif strings.HasPrefix(key, \"on\") {\n    continue\n}\n```\n\nThe `<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.\n\n## Proof of Concept\n\n### Vector 1: `<animate>` sets `href` to `javascript:`\n\n```\nGET /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\n```\n\nAfter template rendering, the SVG contains:\n```xml\n<svg ...>\n    <text ...></text>\n    <a>\n        <animate attributeName=\"href\" values=\"javascript:alert(document.domain)\" begin=\"0s\" fill=\"freeze\"/>\n        <text x=\"50%\" y=\"80%\" fill=\"red\" style=\"font-size:60px\">Click me</text>\n    </a>\n    <text></text>\n</svg>\n```\n\nThe sanitizer passes this through because:\n1. `<animate>` is not in the element blocklist\n2. `attributeName=\"href\"` — key is `attributename`, doesn't start with `on`, not `href` itself\n3. `values=\"javascript:...\"` — key is `values`, not `href`\n\nWhen 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.\n\n### Vector 2: `<set>` modifies event handlers\n\n```\nGET /api/icon/getDynamicIcon?type=8&content=</text><set attributeName=\"onmouseover\" to=\"alert(document.domain)\"/><text>&color=blue\n```\n\nThe `<set>` element dynamically adds an `onmouseover` event handler to the parent element at runtime.\n\n## Attack Scenario\n\n1. Attacker crafts a malicious `getDynamicIcon` URL with XSS payload\n2. Attacker sends the URL to a victim who has an active SiYuan session\n3. Victim clicks/navigates to the URL\n4. SVG renders with Content-Type `image/svg+xml` — browser renders as standalone SVG document\n5. JavaScript executes in the SiYuan server's origin\n6. Attacker steals session cookies, API tokens, or makes authenticated API calls to read/modify notes\n\n## Impact\n\n- **Severity:** CRITICAL (CVSS ~9.1)\n- **Type:** CWE-79 (Improper Neutralization of Input During Web Page Generation)\n- Unauthenticated reflected XSS via SVG injection\n- Executes in the SiYuan application origin, giving full access to authenticated APIs\n- Can chain to: data exfiltration, note modification, configuration theft (API tokens, auth codes)\n- Bypasses the fix for CVE-2026-29183\n\n## Suggested Fix\n\nAdd animation elements to the sanitizer blocklist:\n\n```go\n// In SanitizeSVG, line 250:\nif tag == \"script\" || tag == \"iframe\" || tag == \"object\" || tag == \"embed\" ||\n   tag == \"foreignobject\" || tag == \"animate\" || tag == \"set\" ||\n   tag == \"animatetransform\" || tag == \"animatemotion\" {\n    n.RemoveChild(c)\n    c = next\n    continue\n}\n```\n\nOr additionally check the `values`, `to`, and `from` attributes for `javascript:` patterns:\n\n```go\nif key == \"values\" || key == \"to\" || key == \"from\" {\n    if strings.Contains(val, \"javascript:\") {\n        continue\n    }\n}\n```\n\nAlso consider checking `attributeName` — if it targets `href`, `xlink:href`, or any `on*` attribute, the animation element should be removed entirely.",
  "severity" : [ {
    "type" : "CVSS_V4",
    "score" : "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:H/SI:H/SA:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Go",
      "name" : "github.com/siyuan-note/siyuan/kernel"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "0.0.0-20260310025236-297bd526708f"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/siyuan-note/siyuan/security/advisories/GHSA-5hc8-qmg8-pw27"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-31807"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/siyuan-note/siyuan"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/siyuan-note/siyuan/releases/tag/v3.5.10"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-79" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-03-10T23:49:23Z",
    "nvd_published_at" : "2026-03-10T21:16:50Z"
  }
}