GitHub Security Advisory: GHSA-8q5w-mmxf-48jg
Package: github.com/siyuan-note/siyuan/kernel (GO)
Severity: MODERATE (CVSS 5.4)
CWE: CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
Vulnerable versions: < 0.0.0[PII_REDACTED]3942-62eed37a3263
Patched in: 0.0.0[PII_REDACTED]3942-62eed37a3263

Summary: SiYuan has incomplete fix for CVE-2026-33066: XSS

Details:
### Summary

The incomplete fix for SiYuan's bazaar README rendering enables the Lute HTML sanitizer but fails to block `<iframe>` tags, allowing stored XSS via `srcdoc` attributes containing embedded scripts that execute in the Electron context.

### Affected Package

- **Ecosystem:** Go
- **Package:** github.com/siyuan-note/siyuan
- **Affected versions:** < commit b382f50e1880
- **Patched versions:** >= commit b382f50e1880

### Details

The `renderPackageREADME()` function in `kernel/bazaar/readme.go` renders Markdown README content from bazaar (marketplace) packages into HTML. The original vulnerability allowed stored XSS through unsanitized HTML in READMEs. The fix adds `luteEngine.SetSanitize(true)` to enable Lute's built-in HTML sanitizer.

However, the Lute sanitizer in `lute/render/sanitizer.go` has a critical gap:
1. `<iframe>` is explicitly commented out of `setOfElementsToSkipContent`, so iframe tags pass through.
2. The `srcdoc` attribute is checked against URL-prefix blocklists (`javascript:`, `data:text/html`), but `srcdoc` contains raw HTML content, not a URL. A value like `<img src=x onerror=alert(1)>` does not start with any blocked prefix.
3. The browser renders `srcdoc` HTML in a nested browsing context, executing embedded scripts and event handlers.

The fix correctly blocks direct `<script>` tags, event handler attributes, and `javascript:` protocol links. However:

- `<iframe srcdoc="<script>alert(document.domain)</script>">` passes through because iframe is not blocked and the srcdoc value is raw HTML (not a URL scheme).
- `<iframe srcdoc="<img src=x onerror=alert(document.cookie)>">` also passes because the event handler is inside the srcdoc string value, not a top-level tag attribute.

### PoC

```python
"""
CVE-2026-33066 - Incomplete Sanitization in SiYuan Bazaar README Rendering

Component: kernel/bazaar/readme.go :: renderPackageREADME()
Patch: https://github.com/siyuan-note/siyuan/commit/b382f50e1880ed996364509de5a10a72d7409428
"""

import re
import sys
from html.parser import HTMLParser

ELEMENTS_TO_SKIP_CONTENT = {
    "frame", "frameset",
    # "iframe",  # NOTE: iframe is commented out in the original Go code!
    "noembed", "noframes", "noscript", "nostyle",
    "object", "script", "style", "title",
}

EVENT_ATTRS = {
    "onafterprint", "onbeforeprint", "onbeforeunload", "onerror",
    "onhashchange", "onload", "onmessage", "onoffline", "ononline",
    "onpagehide", "onpageshow", "onpopstate", "onresize", "onstorage",
    "onunload", "onblur", "onchange", "oncontextmenu", "onfocus",
    "oninput", "oninvalid", "onreset", "onsearch", "onselect",
    "onsubmit", "onkeydown", "onkeypress", "onkeyup", "onclick",
    "ondblclick", "onmousedown", "onmousemove", "onmouseout",
    "onmouseover", "onmouseleave", "onmouseenter", "onmouseup",
    "onmousewheel", "onwheel", "ondrag", "ondragend", "ondragenter",
    "ondragleave", "ondragover", "ondragstart", "ondrop", "onscroll",
    "oncopy", "oncut", "onpaste", "onabort"