CVE-2026-73054: SiYuan: WebSocket auth bypass leaks live event stream

GHSA-c8w8-3pqp-wr83HIGHPoC AVAILABLE
Published October 23, 2026
CISO Take

SiYuan's kernel WebSocket checks authentication and quarantines sessions using two different parses of the same URL. An unauthenticated attacker can send a request with duplicated id and type query parameters, get past the access auth code, and receive the live stream of workspace events. That stream includes document titles, notebook names, file paths and structure. Exploitation is trivial and needs no credentials or user interaction, but document body content was not observed in the frames and no write access is possible, so impact is confidentiality only. Risk is moderate: EPSS is low (0.5%, about the 55th percentile), the CVE is not in CISA KEV, and there is no public exploit or Nuclei template. The affected Go module has about 3,043 downstream dependents, and OpenSSF Scorecard is a middling 5.8/10. Upgrade to the patched kernel (commit 67bc300b6ea6, release v3.7.4-alpha.4 or later). Until then, don't expose the kernel port to untrusted networks, and put it behind a VPN or an authenticating reverse proxy.

Sources:NVDGitHub AdvisoryEPSSOpenSSFATLASvulncheck.com

What is the risk?

CVSS 7.5 (High): network-exploitable, low complexity, no privileges or user interaction, confidentiality impact only. Real-world risk depends on exposure. Internet-facing or LAN-shared SiYuan instances protected only by an access auth code are the main concern. Exploitation is a single crafted URI, so the effort required is trivial. There is no KEV listing, no public exploit and low EPSS, so mass exploitation is not currently expected. The missing origin check also allows cross-origin attempts, for example from a malicious web page against a locally running instance. This is a bypass of an earlier fix (GHSA-xp2m-98x8-rpj6), which suggests the area deserves ongoing scrutiny.

How does the attack unfold?

Initial Access
Attacker connects to the kernel WebSocket with a crafted URI containing duplicated id and type parameters, with no credentials.
AML.T0049
Authentication Bypass
The substring-based exemption admits the session while the parsed query resolves to main, so the session lands in the broadcast pool instead of quarantine.
AML.T0107
Collection
The attacker passively receives live broadcast frames covering document and notebook operations.
AML.T0036
Impact
Document titles, notebook names, file paths and workspace structure are disclosed, enabling reconnaissance and targeted follow-on attacks.

What systems are affected?

PackageEcosystemVulnerable RangePatched
Jupyter Notebookgo< 0.0.0-20260731131820-67bc300b6ea60.0.0-20260731131820-67bc300b6ea6
13.5KOpenSSF 5.83.0K dependentsPushed 11d ago79% patched~75d to patchFull package profile →

Do you use Jupyter Notebook? You're affected.

How severe is it?

CVSS 3.1
7.5 / 10
EPSS
0.4%
chance of exploitation in 30 days
Higher than 35% of all CVEs
Exploitation Status
Exploit Available
Exploitation: MEDIUM
Sophistication
Trivial
Exploitation Confidence
medium
○Public PoC indexed (trickest/cve)
Composite signal derived from CISA KEV, VulnCheck KEV, CISA SSVC, EPSS, Metasploit, Exploit-DB, trickest/cve, Nuclei templates, and inthewild.io exploitation reports.

What is the attack surface?

AVACPRUISCIA
AVNetwork
ACLow
PRNone
UINone
SUnchanged
CHigh
INone
ANone

What should I do?

5 steps
  1. Upgrade the SiYuan kernel to a build that includes commit 67bc300b6ea6 (v3.7.4-alpha.4 or later). The Go module is patched at 0.0.0-20260731131820-67bc300b6ea6.

  2. Until patched, don't expose the kernel port directly. Restrict access with a VPN, firewall rules or an authenticating reverse proxy.

  3. Have the reverse proxy reject /ws requests that carry duplicated id or type query keys, and enforce an Origin allowlist on the /ws path.

  4. Detection: review access logs for WebSocket upgrade requests to /ws with repeated id= or type= parameters, especially from unauthenticated or external sources.

  5. Review any workspaces exposed to the internet for signs of unexpected connections, and treat document titles and structure as potentially disclosed.

How is it classified?

Which compliance frameworks are affected?

This CVE is relevant to:

ISO 42001
A.7.2-Data for development and enhancement of AI systems
NIST AI RMF
MANAGE 2.3-Responses to risks of unknown or emergent origin are in place
OWASP LLM Top 10
LLM03-Supply Chain

Frequently Asked Questions

What is CVE-2026-73054?

SiYuan's kernel WebSocket checks authentication and quarantines sessions using two different parses of the same URL. An unauthenticated attacker can send a request with duplicated id and type query parameters, get past the access auth code, and receive the live stream of workspace events. That stream includes document titles, notebook names, file paths and structure. Exploitation is trivial and needs no credentials or user interaction, but document body content was not observed in the frames and no write access is possible, so impact is confidentiality only. Risk is moderate: EPSS is low (0.5%, about the 55th percentile), the CVE is not in CISA KEV, and there is no public exploit or Nuclei template. The affected Go module has about 3,043 downstream dependents, and OpenSSF Scorecard is a middling 5.8/10. Upgrade to the patched kernel (commit 67bc300b6ea6, release v3.7.4-alpha.4 or later). Until then, don't expose the kernel port to untrusted networks, and put it behind a VPN or an authenticating reverse proxy.

Is CVE-2026-73054 actively exploited?

Proof-of-concept exploit code is publicly available for CVE-2026-73054, increasing the risk of exploitation.

How to fix CVE-2026-73054?

1. Upgrade the SiYuan kernel to a build that includes commit 67bc300b6ea6 (v3.7.4-alpha.4 or later). The Go module is patched at 0.0.0-20260731131820-67bc300b6ea6. 2. Until patched, don't expose the kernel port directly. Restrict access with a VPN, firewall rules or an authenticating reverse proxy. 3. Have the reverse proxy reject /ws requests that carry duplicated id or type query keys, and enforce an Origin allowlist on the /ws path. 4. Detection: review access logs for WebSocket upgrade requests to /ws with repeated id= or type= parameters, especially from unauthenticated or external sources. 5. Review any workspaces exposed to the internet for signs of unexpected connections, and treat document titles and structure as potentially disclosed.

What systems are affected by CVE-2026-73054?

This vulnerability affects the following AI/ML architecture patterns: Self-hosted knowledge management and note-taking platforms, AI-assisted knowledge bases, Real-time WebSocket event services.

What is the CVSS score for CVE-2026-73054?

CVE-2026-73054 has a CVSS v3.1 base score of 7.5 (HIGH). The EPSS exploitation probability is 0.41%.

What is the AI security impact?

Affected AI Architectures

Self-hosted knowledge management and note-taking platformsAI-assisted knowledge basesReal-time WebSocket event services

MITRE ATLAS Techniques

AML.T0036Data from Information Repositories
AML.T0049Exploit Public-Facing Application
AML.T0107Exploitation for Defense Evasion

Compliance Controls Affected

ISO 42001: A.7.2
NIST AI RMF: MANAGE 2.3
OWASP LLM Top 10: LLM03

What are the technical details?

Original Advisory

### Summary Two checks on the same WebSocket request URI parse it differently. The authentication exemption for keepalive sessions matches raw substrings, while the quarantine introduced to contain those sessions reads a parsed query parameter. Because Go's `url.Values.Get` returns only the first value for a repeated key, a single URI can satisfy the exemption and still resolve to a non-auth session identity. The result is that an unauthenticated remote caller connects to the kernel WebSocket with a valid access auth code configured, is placed in the general broadcast pool rather than the quarantined pool, and receives the live event stream. ### Details **The exemption matches substrings.** `kernel/server/serve.go:1222` on the development branch, `:1074` on master: ```go authOk = strings.Contains(s.Request.RequestURI, "/ws?app=siyuan") && strings.Contains(s.Request.RequestURI, "&id=auth&type=auth") ``` Neither operand is parsed. Any URI containing both literals is exempted, regardless of what the query actually resolves to. **The quarantine parses.** Commit `1e370e373` added the containment for exempted sessions at `kernel/util/websocket.go:171`: ```go id = session.Request.URL.Query().Get("id") return "auth" == id ``` `url.Values.Get` returns the first value for a repeated key. **The differential.** For the URI: ``` /ws?app=siyuan&id=main&type=main&id=auth&type=auth ``` - It contains `/ws?app=siyuan` and `&id=auth&type=auth`, so `authOk` is true. No cookie, no JWT and no access auth code are required. - `Query().Get("id")` returns `main`, so `IsAuthSession` is false. `AddPushChan` files the session in `sessions`, the broadcast pool, rather than in `authSessions`. - `Query().Get("type")` returns `main`, so the session matches `BroadcastByType("main", ...)`. - Without a valid `X-Auth-Token` the publish flag is never set, so `isPublishSession()` does not exclude it either. Every guard that should have caught the session keys off a different parse than the one that admitted it. **No origin validation.** `CheckOrigin` does not appear on the `/ws` path, so the cross-origin vector described in the parent advisory also remains available. **Distinction from the existing broadcast-pool advisory.** GHSA-mw8r-mw84-88v2 concerns the publish port, where an anonymous session is expected to connect and the defect is that broadcast content is not gated for it afterwards. This report concerns the kernel port with an access auth code configured, where the session should never be admitted in the first place. The leaked data overlaps because both end in the same broadcast pool, but the mechanisms and the affected deployments are different, and gating publish sessions does not close this path. ### Proof of Concept Kernel port, `--accessAuthCode` set. Three WebSocket connections, none carrying credentials of any kind. | Socket | Query | Result | |---|---|---| | A, baseline | `?app=siyuan&id=main&type=main` | Rejected, closed 1002, 0 frames | | B, control | `?app=siyuan&id=auth&type=auth` | Connects, 0 frames | | C, attack | `?app=siyuan&id=main&type=main&id=auth&type=auth` | Connects, 19 to 30 frames across two runs | Socket A establishes that the access auth code is enforced. Socket B establishes that the existing quarantine works exactly as intended, admitting the keepalive session but delivering nothing to it. Socket C differs from B only in the duplicated parameters, and receives the event stream. Frames observed on socket C included `savedoc` (`"action":"create","data":{"Root":{"ID": ...`), `transactions` (`"action":"updateAttrs"` carrying document titles), `filetreeSortChanged` (the notebook's complete ordered `childIDs`), `create` (a notebook object including its `name`), and `backgroundtask`. A canary string placed inside a document body did not appear in any frame, on a full-text search of all captured frames. ### Impact An unauthenticated remote caller obtains the kernel's live event stream on a deployment protected by an access auth code, with no user interaction and no prior knowledge of the instance. Precisely what is disclosed: document identifiers and titles, notebook identifiers and names, file paths, the complete ordered child structure of notebooks, and the full stream of create, update and delete operations as they occur. Document body content is not present in the observed frames. That set corresponds to the disclosure claimed by GHSA-xp2m-98x8-rpj6, which means the remediation for that advisory is bypassable rather than incomplete in scope. The absence of origin validation on the endpoint additionally preserves the cross-origin reachability described there. Confidentiality only. No frames observed permitted writes. ### Suggested fix Make both checks agree, and stop re-parsing attacker-controlled input after admission. 1. In the exemption, parse the query rather than matching substrings, and require `id` and `type` each to equal `auth` exactly. 2. Reject requests carrying duplicated query keys on this endpoint, so no URI can present two identities. 3. Record the exemption as a flag on the session at connect time, and have `IsAuthSession` read that flag rather than re-parsing the request. A session admitted under the keepalive exemption is then quarantined by construction, independent of how its URI is read later. Adding origin validation to `/ws` would additionally close the cross-origin vector.

Exploitation Scenario

An attacker scans for exposed SiYuan instances that use an access auth code. They open a WebSocket to /ws?app=siyuan&id=main&type=main&id=auth&type=auth with no credentials. The substring check admits the session as a keepalive connection, while the quarantine parses id as main and files it in the general broadcast pool. The attacker passively collects frames such as savedoc, transactions and filetreeSortChanged, which reveal document titles, notebook names and structure in real time. They use this to map the organization's internal projects, including AI and security work, and to prepare targeted phishing or further attacks. The same flaw can be triggered cross-origin from a malicious web page against a victim's locally running instance.

Weaknesses (CWE)

CWE-287 — Improper Authentication: When an actor claims to have a given identity, the product does not prove or insufficiently proves that the claim is correct.

  • [Architecture and Design] Use an authentication framework or library such as the OWASP ESAPI Authentication feature.

Source: MITRE CWE corpus.

CVSS Vector

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

Timeline

Published
October 23, 2026
Last Modified
October 23, 2026
First Seen
October 23, 2026

Related Vulnerabilities