high · 8.6CVE-2026-72810Sep 3, 2026

CVE-2026-72810: SiYuan WebSocket Broadcast Publish-Boundary Bypass

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

SiYuan's publish-mode WebSocket connection shares the same broadcast pool as authenticated sessions, so an anonymous reader can silently receive every live edit made in the workspace, including…

Packagegithub.com/siyuan-note/siyuan/kernel
Ecosystemgo
Affected< 0.0.0-20260723013612-ba948639d7f6
Fixed in0.0.0-20260723013612-ba948639d7f6
CVE-2026-72810: SiYuan WebSocket Broadcast Publish-Boundary Bypass

The problem

SiYuan's publish service (port 6808) accepts anonymous WebSocket connections via HandleConnect, which admits the injected RoleReader token and registers the session in the same sessions pool used by authenticated clients.

The kernel's broadcast functions (Broadcast, broadcastOthers, broadcastOtherAppMains) push every content event to every session in that pool with no role or publish-access check. The isPublish flag on a session was only consulted to send a "service closed" notice, not to gate content.

Because these events originate from the kernel's edit pipeline and go directly to open sockets, none of the HTTP publish-access filters apply. An anonymous reader holding the socket open receives block DOM, attributes, titles, notebook names, and document structure for every edit, including password-protected, publish-forbidden, and unpublished documents.

Proof of concept

A working proof-of-concept for CVE-2026-72810 in github.com/siyuan-note/siyuan/kernel, with the exact payload below.

bash
# 1. Open an anonymous WebSocket to the publish port (no token, no password)
#    Works as long as Publish.Auth.Enable is false (the default)
wscat -c 'ws://127.0.0.1:6808/ws'

# 2. Keep the connection open. While an admin edits documents, the socket
#    passively receives live push events such as:
#
#  {"cmd":"transactions","data":[{"doOperations":[{"action":"updateAttrs",
#    "data":{"name":"WS_LEAK_SECRET_9931"},"id":"<blockID>",
#    "rootID":"<passwordProtectedDocID>"}]}]}
#
#  {"cmd":"createDoc","data":{"box":"CritChain",
#    "path":"/WS_SECRET_DOC_7742.sy","title":"WS_SECRET_DOC_7742"}}
#
# No HTTP request beyond the WebSocket upgrade is needed.
# Content from protected, forbidden, and unpublished documents arrives unfiltered.

The root cause is CWE-862 (Missing Authorization) on the WebSocket broadcast path. AddPushChan places publish sessions into the same pool as authenticated sessions, and every broadcast function iterates the pool unconditionally, writing content events to all members.

The patch at commit ba948639d7f6 makes the isPublish flag gate content events, not just the service-closed notice. Before the fix, publish sessions received the full unfiltered event stream; after it, broadcast functions skip or filter content events for sessions where isPublish is true, applying the same publish-access checks used on the HTTP content path.

The fix

Update to the patched pseudo-version 0.0.0-20260723013612-ba948639d7f6 (commit ba948639d7f6bd5594ce584072dc68310da87a68) or any release that includes it. As a short-term workaround, enable publish Basic Auth (Publish.Auth.Enable = true) or disable publish mode entirely to prevent anonymous WebSocket admission.

Reporter not attributed.

References: [1][2][3][4][5]

Related research