CVE-2026-31809 Overview
SiYuan is a personal knowledge management system that contains a Cross-Site Scripting (XSS) vulnerability in its SVG sanitizer component. Prior to version 3.5.10, SiYuan's SanitizeSVG function checks href attributes for the javascript: prefix using strings.HasPrefix(). However, inserting ASCII tab ( ), newline ( ), or carriage return ( ) characters inside the javascript: string bypasses this prefix check. Browsers strip these characters per the WHATWG URL specification before parsing the URL scheme, so the JavaScript still executes. This allows an attacker to inject executable JavaScript into the unauthenticated /api/icon/getDynamicIcon endpoint, creating a reflected XSS vulnerability. Notably, this is a second bypass of the fix for CVE-2026-29183 (fixed in v3.5.9).
Critical Impact
Attackers can execute arbitrary JavaScript in victim browsers through the unauthenticated /api/icon/getDynamicIcon endpoint, potentially leading to session hijacking, credential theft, or malicious actions performed under the victim's identity.
Affected Products
- B3log SiYuan versions prior to 3.5.10
- SiYuan installations with exposed /api/icon/getDynamicIcon endpoints
Discovery Timeline
- 2026-03-10 - CVE-2026-31809 published to NVD
- 2026-03-11 - Last updated in NVD database
Technical Details for CVE-2026-31809
Vulnerability Analysis
This vulnerability is a reflected Cross-Site Scripting (XSS) flaw that stems from an incomplete fix for a previously disclosed vulnerability (CVE-2026-29183). The core issue lies in SiYuan's SVG sanitization logic, specifically in the SanitizeSVG function which is responsible for filtering potentially malicious content from SVG data before rendering.
The sanitizer attempts to block JavaScript execution by checking if href attributes begin with the javascript: protocol. However, the implementation uses a simple string prefix check that does not account for control characters that browsers automatically strip during URL parsing.
Root Cause
The root cause is the use of strings.HasPrefix() for security-sensitive URL scheme validation. This approach fails to consider that the WHATWG URL specification instructs browsers to remove ASCII tab, newline, and carriage return characters before scheme parsing. An attacker can insert these control characters within the javascript: string (e.g., java\tscript:, java\nscript:, or java\rscript:) to evade the prefix check while still achieving JavaScript execution when the browser normalizes the URL.
This represents a classic filter bypass pattern where the sanitization logic operates on a different representation of the input than the component that ultimately processes it (the browser's URL parser).
Attack Vector
The attack vector is network-based and requires user interaction. An attacker crafts a malicious URL targeting the unauthenticated /api/icon/getDynamicIcon endpoint with an SVG payload containing a specially crafted href attribute. When a victim clicks the malicious link or visits a page that loads the malicious SVG, their browser strips the control characters and executes the embedded JavaScript code.
The vulnerability is accessible without authentication, increasing its exploitability. The attacker can leverage this for:
- Session token theft via document.cookie access
- Credential harvesting through injected login forms
- Malware distribution by redirecting users to malicious sites
- Defacement of the knowledge management interface
For detailed technical information including proof-of-concept examples, refer to the GitHub Security Advisory.
Detection Methods for CVE-2026-31809
Indicators of Compromise
- HTTP requests to /api/icon/getDynamicIcon containing encoded control characters (%09, %0A, %0D) within URL parameters
- SVG content containing href attributes with whitespace or control characters before or within the javascript: string
- Web server logs showing unusual GET requests to the dynamic icon API with long or obfuscated query parameters
- JavaScript execution from SVG contexts that should not contain executable code
Detection Strategies
- Implement Web Application Firewall (WAF) rules to detect and block requests containing control characters in combination with javascript: patterns
- Monitor HTTP logs for requests to /api/icon/getDynamicIcon with suspicious URL-encoded sequences
- Deploy browser-based Content Security Policy (CSP) headers to mitigate XSS impact even if the vulnerability is exploited
- Configure SIEM rules to correlate requests to vulnerable endpoints with anomalous user behavior patterns
Monitoring Recommendations
- Enable verbose logging on the SiYuan application server to capture all requests to API endpoints
- Set up alerting for multiple failed or suspicious requests to the /api/icon/getDynamicIcon endpoint from single IP addresses
- Monitor for user reports of unexpected JavaScript behavior or redirects when using the SiYuan interface
- Review Content Security Policy violation reports if CSP is implemented to detect attempted XSS exploitation
How to Mitigate CVE-2026-31809
Immediate Actions Required
- Upgrade SiYuan to version 3.5.10 or later immediately
- If immediate upgrade is not possible, consider temporarily restricting access to the /api/icon/getDynamicIcon endpoint via reverse proxy or firewall rules
- Implement strong Content Security Policy headers with script-src directives to limit JavaScript execution contexts
- Review access logs for any evidence of prior exploitation attempts
Patch Information
This vulnerability is fixed in SiYuan version 3.5.10. The patch addresses the SVG sanitization bypass by implementing more robust URL scheme validation that properly handles control characters before checking for dangerous protocols. Users should update to this version or later through their standard update mechanism. For additional details, see the GitHub Security Advisory.
Workarounds
- Restrict access to the /api/icon/getDynamicIcon endpoint using authentication middleware or IP-based access controls
- Deploy a Web Application Firewall with rules to strip or block requests containing control characters in URL parameters
- Implement a strict Content Security Policy that blocks inline JavaScript execution: Content-Security-Policy: script-src 'self'
- Consider disabling dynamic icon functionality if it is not critical to your workflow until the patch can be applied
# Example nginx configuration to restrict access to the vulnerable endpoint
location /api/icon/getDynamicIcon {
# Temporarily deny access to vulnerable endpoint
deny all;
# Or restrict to trusted IPs only
# allow 10.0.0.0/8;
# deny all;
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

