GHSA-xp2m-98x8-rpj6 SiYuan Vulnerable to Cross-Origin WebSocket Hijacking via Authentication Bypass — Unauthenticated Information Disclosure
Cross-Origin WebSocket Hijacking via Authentication Bypass — Unauthenticated Information DisclosureSummarySiYuan's WebSocket endpoint (`/ws`) allows unauthenticated connections when specific URL parameters are provided (`?app=siyuan&id=auth&type=auth`). This bypass, intended for the login page to keep the kernel alive, allows any external client — including malicious websites via cross-origin WebSocket — to connect and receive all server push events in real-time. These events leak sensitive document metadata including document titles, notebook names, file paths, and all CRUD operations performed by authenticated users.Combined with the absence of `Origin` header validation, a malicious website can silently connect to a victim's local SiYuan instance and monitor their note-taking activity.Affected Component**File:** `kernel/server/serve.go:728-731`**Function:** `serveWebSocket()` → `HandleConnect` handler**Endpoint:** `GET /ws?app=siyuan&id=auth&type=auth` (unauthenticated)**Version:** SiYuan <= 3.5.9Root CauseThe WebSocket `HandleConnect` handler has a special case bypass (line 730) intended for the authorization page:Three issues combine:**Authentication bypass via URL parameters:** Any client connecting with `?app=siyuan&id=auth&type=auth` bypasses all authentication checks.**Full broadcast membership:** The bypassed session is added to the broadcast list via `util.AddPushChan(s)`, receiving ALL `PushModeBroadcast` events — the same events sent to authenticated clients.**No Origin validation:** The WebSocket endpoint does not check the `Origin` header, allowing cross-origin connections from any website.Proof of Concept**Tested and confirmed on SiYuan v3.5.9 (Docker) with `accessAuthCode` configured.**1. Direct unauthenticated connection2. Cross-origin attack from malicious website3. Confirmed leaked eventsThe following events are received by the unauthenticated WebSocket:| Event | Leaked Data |
|-------|-------------|
| `savedoc` | Document root ID, operation data |
| `transactions` | Document title, ID, attrs (new/old) |
| `create` | Document path, notebook info (name, ID) |
| `rename` | New document title, path, notebook ID |
| `renamenotebook` | New notebook name, notebook ID |
| `removeDoc` | Document deletion event |4. Cross-origin connection confirmed**Result:** Connection succeeds — no Origin validation.Attack ScenarioVictim runs SiYuan desktop (Electron, listens on `localhost:6806`) or Docker instanceVictim has `accessAuthCode` configured (server is password-protected)Victim visits `attacker.com` in any browserAttacker's JavaScript connects to `ws://localhost:6806/ws?app=siyuan&id=spy&type=auth`WebSocket connection bypasses authenticationAttacker silently monitors ALL document operations in real-time:Document titles ("Q4 Financial Results", "Employee Reviews", "Patent Draft")Notebook names ("Personal", "Work - Confidential")File paths and document IDsCreate/rename/delete operationsAttacker builds a profile of the victim's note-taking activity without any visible indicationImpact**Severity:** HIGH (CVSS ~7.5)**Type:** CWE-287 (Improper Authentication), CWE-200 (Exposure of Sensitive Information), CWE-1385 (Missing Origin Validation in WebSockets)Authentication bypass on WebSocket endpoint when `accessAuthCode` is configuredCross-origin WebSocket hijacking — any website can connect to local SiYuan instanceReal-time information disclosure of document metadata (titles, paths, operations)No user interaction required beyond visiting a malicious websiteAffects both Electron desktop and Docker/server deploymentsSilent — no visible indication to the userSuggested Fix1. Remove the URL parameter authentication bypass2. Add Origin header validation3. Separate keepalive from broadcastIf the auth page needs a WebSocket for keepalive, create a separate endpoint (`/ws-keepalive`) that only handles ping/pong without receiving broadcast events. Do not add keepalive sessions to the broadcast push channel.
CVSS v4.0 score: 5.3