Oct 3, 2026·6 min read·4 visits
Unauthenticated or anonymous users can exploit missing authorization checks in SiYuan's block APIs to retrieve private note contents and map document metadata.
A high-severity missing authorization vulnerability (CWE-862) exists in the SiYuan note-taking application before v3.7.4. Seventeen block metadata and content-derived endpoints within kernel/api/block.go lack proper publish-access and role-based checks. This allows low-privilege or anonymous users in publish mode to bypass workspace restrictions and disclose private block content, trace workspace structures, map document indexes, and verify the existence of private notes. The vulnerability is addressed in version v3.7.4.
SiYuan is an open-source, self-hosted, local-first note-taking application designed for personal knowledge management. The application features a 'Publish' mode that allows users to share specific notebooks or documents with external readers over the network. In versions prior to v3.7.4, a major architectural gap exists where the backend exposes internal block APIs without proper privilege verification.\n\nSpecifically, seventeen block metadata and content-derived endpoints located in kernel/api/block.go fail to enforce publication-access boundaries. While these endpoints verify basic user authentication, they do not confirm whether the requested block belongs to an authorized, public, or decrypted notebook. Consequently, any authenticated or anonymous user with access to the publish-mode interface can query internal block structures directly.\n\nThis gap allows unauthorized actors to bypass notebook encryption barriers and systematically exfiltrate metadata. An attacker can map document trees, verify document structures, and extract specific text content. The exposure is classified under CWE-862 (Missing Authorization) and represents a severe data disclosure vector.\n\nmermaid\ngraph LR\n A["Client Request"] --> B["API Router"]\n B --> C["model.CheckAuth"]\n C --> D["Vulnerable Block APIs"]\n D -->|No Publish Check| E["Private Notebook Storage"]\n D -->|No Context Filtering| F["Metadata Exfiltration"]\n
The root cause of this vulnerability lies in the missing authorization checks inside kernel/api/block.go. When SiYuan processes incoming API requests for blocks, it utilizes standard middleware handlers to manage user sessions. However, the handlers associated with the seventeen vulnerable endpoints only execute model.CheckAuth to verify if a session exists. They do not validate client roles, publish status, or the ownership of the requested resources.\n\nIn a standard secure deployment, read-only or public access roles should only query resources explicitly marked as public. The application fails to supply this role-based context-filtering logic during the processing of requests such as getRefText or checkBlockExist. Because block identifiers are predictable or can be systematically guessed, the lack of isolation allows unrestricted block access across separate notebooks.\n\nFurthermore, the application handles notebook-level encryption via 'encrypted boxes'. Because endpoints like getRefText resolve content using global block-retrieval functions without first checking the box's encryption state or authorization requirements, they bypass notebook-level security measures entirely. This lack of access control exposes sensitive information from private notebooks to anyone who can query the local API port or the public web interface.
To understand the technical gap, analyze the vulnerable implementation of the getRefText endpoint within kernel/api/block.go. The endpoint parses the request arguments, reads the block identifier, and retrieves the text directly from the model layer. The vulnerable function does not evaluate the current user context or verify if the block belongs to a published workspace.\n\ngo\n// VULNERABLE CODE PATH\nfunc getRefText(c *gin.Context) {\n // ...\n id := arg["id"].(string)\n if util.InvalidIDPattern(id, ret) {\n return\n }\n var refText string\n // Directly retrieves the reference text without checking role or publication state\n if notebook, ok := arg["notebook"].(string); ok && notebook != "" && model.IsEncryptedBox(notebook) {\n refText = model.GetBlockRefTextInBox(id, notebook)\n } else {\n refText = model.GetBlockRefText(id)\n }\n // ...\n ret.Data = refText\n}\n\n\nThe fix commit bd067a4fe9b208c0858d8d9dc6220dc8affc403e addresses this gap by implementing access control checks before accessing the storage engine. The application now calls authorization filters such as holdBlockRequest and isBlockPublishAccessible to validate that the requested block ID lies within a resource the user is authorized to view.\n\ngo\n// PATCHED CODE PATH\nfunc getRefText(c *gin.Context) {\n // ...\n id := arg["id"].(string)\n if util.InvalidIDPattern(id, ret) {\n return\n }\n boxID := encryptedNotebookFromArg(arg)\n // Step 1: Hold request if authorization fails for the given notebook\n if !holdBlockRequest(c, ret, boxID) {\n return\n }\n // Step 2: Explicitly verify if the block is accessible under current publish rules\n if !isBlockPublishAccessible(c, id, boxID) {\n ret.Code = -1\n ret.Msg = "Unauthorized access"\n return\n }\n var refText string\n if boxID != "" && model.IsEncryptedBox(boxID) {\n refText = model.GetBlockRefTextInBox(id, boxID)\n } else {\n refText = model.GetBlockRefText(id)\n }\n // ...\n ret.Data = refText\n}\n
Exploitation of CVE-2026-74904 is straightforward and does not require sophisticated techniques. An attacker needs access to the network interface of a running SiYuan instance where publish mode or read-only access is enabled. Since the endpoints do not validate block ownership, the attacker can systematically scan block IDs to exfiltrate data.\n\nTo retrieve private text content, the attacker issues a HTTP POST request to the /api/block/getRefText endpoint. By submitting the target block ID in the request body, the server responds with the corresponding text. This process bypasses any publication restrictions configured within the workspace.\n\nbash\ncurl -s -X POST http://localhost:6806/api/block/getRefText \\\n -H "Content-Type: application/json" \\\n -d '{"id":"20260724000021-privateid"}'\n\n\nAdditionally, the /api/block/checkBlockExist endpoint functions as an existence oracle. Attackers can leverage this endpoint to perform brute-force discovery of block identifiers across private notebooks. This feedback loop allows attackers to construct a precise map of document structures and confirm the presence of specific keywords or document assets.
The impact of this vulnerability is significant for users relying on SiYuan's multi-user features, public sharing, or self-hosted web servers. Because block metadata and reference texts represent actual document content, exploitation leads to direct intellectual property exposure and credential leakage if secrets are stored in private notes. The vulnerability violates the primary security boundaries established by notebook encryption.\n\nThe Common Vulnerability Scoring System (CVSS) v4.0 evaluates this flaw with a score of 8.7, indicating high severity. The CVSS v3.1 vector is CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N. The impact is restricted to confidentiality, as the vulnerable endpoints do not allow unauthorized write operations or system command execution.\n\nDue to the simplicity of sending automated HTTP requests, the likelihood of targeted exploitation on public-facing servers is high. While the EPSS score remains low at 0.50% due to the novelty of the vulnerability, security administrators must treat any internet-exposed instance as highly vulnerable if publish mode is active.
The primary remediation strategy is upgrading the SiYuan note-taking application to version v3.7.4, v3.8.0, or later. These versions incorporate the necessary validation checks in the backend kernel, preventing unauthorized block metadata queries. Administrators should deploy the updated container image or binary to ensure all internal routes are secured.\n\nIf immediate upgrading is not possible, administrators should disable the 'Publish' mode feature entirely to prevent public-facing exposure. Restricting network access to the application's API port (default 6806) via firewall rules or reverse proxy access control lists will prevent external actors from reaching the vulnerable endpoints.\n\nFurthermore, deploying custom Web Application Firewall (WAF) rules can help detect and block unauthorized API requests targeting the /api/block/* paths. Security teams should monitor logs for unusual volumes of POST requests to these endpoints, especially from IP addresses associated with public or anonymous reader sessions.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
siyuan siyuan-note | < 3.7.4 | 3.7.4 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-862 |
| Attack Vector | Network |
| CVSS v4.0 Score | 8.7 (High) |
| CVSS v3.1 Score | 7.5 (High) |
| EPSS Score | 0.00504 (Percentile: 40.87%) |
| Impact | Information Disclosure |
| Exploit Status | PoC Available |
| KEV Status | Not Listed |
The software does not perform an authorization check when an actor attempts to access a resource or perform an action.
CVE-2026-74802 is a critical Cross-Site WebSocket Hijacking (CSWSH) vulnerability in the SiYuan knowledge workspace application. Due to improper origin validation across multiple internal WebSocket endpoints, an attacker can hijack active authenticated sessions when a victim visits an untrusted external page. This allows the attacker to route malicious network traffic through the victim's localized SiYuan server, establishing an authenticated network pivot and facilitating Server-Side Request Forgery (SSRF).
A critical cross-site WebSocket hijacking (CSWSH) vulnerability in headroomlabs-ai/headroom prior to version 0.35.0 allows unauthorized external origins to establish connection channels to the Headroom proxy, enabling arbitrary prompt execution and remote code execution through local tool integration.
A critical vulnerability exists in the praxis-proxy library where the omission of default limits on HTTP/2 server options allows remote attackers to trigger a Denial of Service (DoS) using an HPACK compression bomb and flow-control window stalls. This vulnerability is cataloged as GHSA-cjcg-cxmh-9wcr.
A Use-After-Free (UAF) vulnerability exists in the sqlite3-ruby native C extension when marshaling arguments for user-defined SQLite aggregate functions with multiple arguments. Due to temporary heap-allocated argument arrays not being registered with the Ruby Garbage Collector, active objects can be prematurely reclaimed, resulting in memory corruption or process-level crashes.
An unauthenticated remote denial of service vulnerability exists in @fastify/busboy versions 3.1.0 through 3.2.0. The vulnerability is caused by an integer wrap-around in the Boyer-Moore-Horspool algorithm implementation inside the sbmh submodule when initializing skip distances. When processing a specific boundary of 252 bytes, the parser triggers an infinite loop, stalling the single-threaded Node.js event loop and exhausting CPU resources.
A critical remote, unauthenticated Denial of Service (DoS) vulnerability in @fastify/busboy (<= 3.2.0) allows attackers to crash the Node.js process. By submitting a crafted multipart/form-data request with a header key matching an inherited property of Object.prototype (like __proto__ or constructor), the internal HeaderParser triggers a synchronous TypeError.