# SiYuan: Publish-boundary bypass via WebSocket broadcast: anonymous readers receive a live unfiltered feed of all edits including protected/forbidden documents (publish mode)

SiYuan publish-mode WebSocket sessions join the same broadcast pool as authenticated ones, so anonymous readers passively receive live edits to protected and forbidden documents.

- Payout: Research
- Severity: high
- Program: SiYuan
- Found by: Shirshakhtml
- Disclosed: 2026-09-03
- CVE: CVE-2026-72810
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-mw8r-mw84-88v2
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-mw8r-mw84-88v2
- Tags: area:web domain:web impact:data-leak kind:research platform:ghsa sev:high tech:websocket technique:source-review vuln:access-control vuln:auth-bypass vuln:info-disclosure

**Target:** SiYuan kernel WebSocket push channel (/ws) on publish port 6808
**Root cause:** Publish RoleReader sessions are registered via AddPushChan into the same session pool as authenticated clients, and broadcast functions write content events to every session without role or publish-access filtering. The isPublish flag only gates the service-closed notice, never content.
**Steps:**
1. Enable publish mode on port 6808 with Publish.Auth.Enable=false.
2. As an anonymous client, open `wss://127.0.0.1:6808/ws` and hold the connection open (no token, no password).
3. Have an administrator edit documents in the workspace, including password-protected and publish-forbidden ones.
4. Observe pushed events on the anonymous socket: `updateAttrs` with `name=WS_LEAK_SECRET_9931` on a block whose `rootID` is a password-protected doc, the title `WS_SECRET_DOC_7742` of a new doc, and a create event carrying notebook name `CritChain` and doc path.
**How found:** Noticed that publish RoleReader sessions are admitted by HandleConnect and added to the same sessions pool via AddPushChan, then read the broadcast functions (Broadcast, broadcastOthers, broadcastOtherAppMains) and saw no role/publish-access check, only the isPublish flag used for the service-closed notice. Realized push events bypass the HTTP publish-access filters entirely.
**Exploitation:** Passive: attacker keeps a publish-surface WebSocket open and receives the kernel's PushModeBroadcast content events (transactions with rendered block DOM, savedoc/create, moveDoc/rename) in real time as an admin edits. No HTTP request beyond the upgrade; no active querying needed.
**Insight:** When a product has a separate read-only/publish surface, check whether its sessions share the same push/broadcast pool as privileged sessions — authorization filters on HTTP handlers do not apply to server-initiated push, so any session flag like isPublish must be enforced at broadcast time.

