GitHub Security Advisory: GHSA-4663-4mpg-879v
Package: github.com/siyuan-note/siyuan/kernel (GO)
Severity: MODERATE (CVSS 0.0)
CWE: CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
Vulnerable versions: < 0.0.0[PII_REDACTED]1550-b382f50e1880
Patched in: 0.0.0[PII_REDACTED]1550-b382f50e1880

Summary: SiYuan has Stored XSS to RCE via Unsanitized Bazaar README Rendering

Details:
# Stored XSS to RCE via Unsanitized Bazaar README Rendering

## Summary

SiYuan's Bazaar (community marketplace) renders package README content without HTML sanitization. The backend `renderREADME` function uses `lute.New()` without calling `SetSanitize(true)`, allowing raw HTML embedded in Markdown to pass through unmodified. The frontend then assigns the rendered HTML to `innerHTML` without any additional sanitization. A malicious package author can embed arbitrary JavaScript in their README that executes when a user clicks to view the package details. Because SiYuan's Electron configuration enables `nodeIntegration: true` with `contextIsolation: false`, this XSS escalates directly to full Remote Code Execution.

## Affected Component

- **README rendering (backend)**: `kernel/bazaar/package.go:635-645` (`renderREADME` function)
- **README rendering (frontend)**: `app/src/config/bazaar.ts:607` (`innerHTML` assignment)
- **Electron config**: `app/electron/main.js:422-426` (`nodeIntegration: true`, `contextIsolation: false`)

## Affected Versions

- SiYuan <= 3.5.9
- 
## Severity

**Critical** — CVSS 9.6 (AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H)

- CWE-79: Improper Neutralization of Input During Web Page Generation (Stored XSS)

Note: This vector requires one click (user viewing the package README), unlike the metadata vector which is zero-click.

## Vulnerable Code

### Backend: `kernel/bazaar/package.go:635-645`

```go
func renderREADME(repoURL string, mdData []byte) (ret string, err error) {
    luteEngine := lute.New()  // Fresh Lute instance — SetSanitize NOT called
    luteEngine.SetSoftBreak2HardBreak(false)
    luteEngine.SetCodeSyntaxHighlight(false)
    linkBase := "https://cdn.jsdelivr.net/gh/" + ...
    luteEngine.SetLinkBase(linkBase)
    ret = luteEngine.Md2HTML(string(mdData))  // Raw HTML in Markdown is PRESERVED
    return
}
```

Compare with SiYuan's own note renderer in `kernel/util/lute.go:81`, which **does** sanitize:

```go
luteEngine.SetSanitize(true)  // Notes ARE sanitized — but Bazaar README is NOT
```

This inconsistency demonstrates that the project is aware of the Lute sanitization API but failed to apply it to Bazaar content.

### Frontend: `app/src/config/bazaar.ts:607`

```typescript
fetchPost("/api/bazaar/getBazaarPackageREADME", {...}, response => {
    mdElement.innerHTML = response.data.html;  // Unsanitized HTML injected into DOM
});
```

The backend returns unsanitized HTML, and the frontend blindly assigns it to `innerHTML` without any client-side sanitization (e.g., DOMPurify).

### Electron: `app/electron/main.js:422-426`

```javascript
webPreferences: {
    nodeIntegration: true,
    contextIsolation: false,
    // ...
}
```

Any JavaScript executing in the renderer has direct access to Node.js APIs.

## Proof of Concept

### Step 1: Create a malicious README

Create a GitHub repository with a valid SiYuan plugin/theme/template structure. The `README.md` contains embedded HTML:

```markdown
# Helpful Producti