Sep 4, 2026·7 min read·44 visits
Unauthenticated remote attackers can query SiYuan's graph endpoints to bypass password protection and extract private document contents and linkages.
SiYuan before version 3.7.4 contains an authentication bypass vulnerability within its graph visualization API endpoints, allowing unauthenticated remote attackers to extract sensitive node metadata and content from password-protected documents.
The SiYuan knowledge management platform is an open-source personal knowledge management system designed to run as a local desktop tool or a self-hosted cloud service. To enable seamless collaboration and knowledge sharing, SiYuan offers a native 'Publish Mode' that exports local notebooks into interactive web interfaces. This capability exposes an external attack surface, as self-hosted instances are frequently connected to public networks to allow remote access for colleagues or public readers.
To manage access controls within this shared model, SiYuan implements a tier-based publishing security schema. Users can designate specific documentation trees as fully public, password-protected, or hidden. The password-protection tier is designed to present an authentication challenge, blocking anonymous users from viewing document indexes, markdown content, and associated assets while keeping the document metadata visually structured in the notebook's navigation map.
Under the hood, SiYuan relies on API endpoints to dynamically render graph layouts that show connections between thoughts, tags, and files. Two primary endpoints, /api/graph/getGraph and /api/graph/getLocalGraph, compile relationship maps based on references found in the notes database. However, prior to version 3.7.4, these endpoints lacked integration with the password authorization layer, leaving a critical gap in the platform's multi-tier access architecture.
The root cause of CVE-2026-72804 is located within the API handler functions defined in kernel/api/graph.go. When processing graph serialization requests, the backend constructs node networks where individual elements correspond to physical files, block paragraphs, or metadata tags. These nodes are populated with real content extracted from the underlying markdown files, including document headers, titles, and text snippets used for visualization labels.
In affected versions, the authorization checks for these graph queries relied exclusively on a simple blacklist filtering mechanism. The handlers invoked model.GetInvisiblePublishAccess to identify files configured as completely hidden (Visible: false) and filtered them out via FilterGraphByPublishIgnore. However, the code failed to execute any verification checks on files configured with the password-protection tier (Visible: true but protected by a cryptographic hash verification).
Because the graph handler functions were stateless with respect to the user's session and did not read client authentication state, they processed and formatted protected notes indiscriminately. Consequently, an anonymous request to the graph endpoints forced the server to serialize the internal contents of all password-protected notes. The resulting API response contained sensitive paragraph blocks, exposing information directly to unauthorized requestors in violation of CWE-200 rules.
The security patch committed in version 3.7.4 refactors the graph-filtering pipeline to use a context-aware authorization model. In the vulnerable version, the graph endpoints did not receive the Gin context container *gin.Context within the model's core filtering utility. This prevented the application from verifying if the client possessed the necessary browser cookies confirming a successful password submission.
// Patch snippet in kernel/api/graph.go
- publishIgnore := model.GetInvisiblePublishAccess(publishAccess)
- nodes, links = model.FilterGraphByPublishIgnore(publishIgnore, nodes, links)
+ nodes, links = model.FilterGraphByPublishAccess(c, publishAccess, nodes, links)The refactored function, FilterGraphByPublishAccess, dynamically queries the client's HTTP cookie jar for each node mapped during graph rendering. When a node's path is associated with a password-protected document, the system extracts the password salt from the server config and calls CheckPublishAuthCookie using the context object c. If the client does not provide the matching SHA-256 cookie, the server excludes the node from the returned array.
// Validation logic inside kernel/model/publish_access.go
passwordID, password := GetPathPasswordByPublishAccess(node.Box, node.Path, publishAccess)
if password != "" && !CheckPublishAuthCookie(c, passwordID, password) {
continue // Rejects unauthorized graph nodes dynamically
}Furthermore, the patch implements a cascading cleanup phase. If a node is eliminated due to authorization failure, the engine automatically removes all downstream link components referencing that specific node. This ensures that metadata about hidden nodes (such as connection weights or size parameters) does not leak to unauthorized clients through remaining edge elements.
To exploit CVE-2026-72804, an attacker does not require special administrative privileges or pre-existing credentials. The attack is entirely unauthenticated and can be conducted using basic command-line utilities. An external attacker first scans public instances of SiYuan, identifying self-hosted sites that expose a public interface containing protected folders.
Instead of accessing the frontend, which handles authorization via form dialogs and cookie validation, the attacker targets the graph serialization endpoint directly. By issuing an unauthenticated HTTP POST request to the /api/graph/getGraph endpoint, the attacker forces the backend to compile the node topology. The payload requires no special parameter headers and can be sent with an empty JSON object.
curl -s -X POST http://siyuan.target/api/graph/getGraph \
-H "Content-Type: application/json" \
-d '{}' | jq .The server responds with a complete layout of the graph database, bypassing the front-end login wall entirely. Within the returned JSON response, the data.nodes array lists every active node in the document hierarchy. Attackers can parse the resulting block-level elements to retrieve private journal entries, embedded keys, system passwords, and the overall linkage structure of the restricted pages.
The severity of CVE-2026-72804 is rated as Critical with a CVSS v4.0 base score of 9.2. This high rating is a direct consequence of the complete lack of authorization checks on a public API endpoint, which allows unauthenticated remote actors to bypass access controls without user interaction. The vulnerability has a severe impact on the confidentiality of user deployments, particularly those containing sensitive commercial or personal intellectual property.
From an adversarial standpoint, the vulnerability maps directly to collection techniques such as T1005 (Data from Local System) and credential access techniques such as T1552 (Unsecured Credentials). Users frequently store infrastructure access credentials, SSH keys, private keys, and environment variables within password-protected blocks. Because this information is serialized inside node titles and labels, exploitation leads to direct leakage of critical administrative secrets.
Moreover, the leakage of the complete reference topology allows adversaries to conduct advanced profiling of the targeted system. By analyzing the structural connections between hidden documents and public indices, attackers can deduce internal organizational charts, product development cycles, or sensitive system relationships. This structural information acts as a force multiplier for subsequent targeted attacks or social engineering campaigns.
The absolute mitigation for CVE-2026-72804 is to update the SiYuan platform to version 3.7.4 or later. This release completely patches the vulnerability by enforcing server-side authorization checks on all graph-related API handlers. Deployments running inside containerized environments should verify that their Docker compose files pull the updated image and restart the platform services to apply the security controls.
When immediate patching is impossible, network-level workarounds can protect vulnerable deployments. Administrators should implement request-filtering policies within an upstream reverse proxy or Web Application Firewall (WAF) to block external traffic directed to the vulnerable endpoints. Setting rules in Nginx, Caddy, or Apache to deny external access to /api/graph/getGraph and /api/graph/getLocalGraph will prevent direct exploitation without affecting normal document reading.
# Upstream block in reverse proxy config
location ~ ^/api/graph/(getGraph|getLocalGraph)$ {
deny all;
return 403;
}Additionally, users can mitigate immediate exposure by modifying the publishing configurations of sensitive documents. Transitioning the status of critical folders from 'Password Protected' to 'Hidden' ensures they are completely excluded from the graph compiling process by the legacy FilterGraphByPublishIgnore mechanism. Security teams should also inspect proxy logs for any unexpected POST requests targeting graph endpoints that yield successful HTTP 200 responses without matching authentication cookies.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
siyuan siyuan-note | < 3.7.4 | 3.7.4 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-200 |
| Attack Vector | Network (AV:N) |
| CVSS v4.0 Score | 9.2 (Critical) |
| EPSS Score | 0.00255 (16.82%) |
| Impact | Confidentiality Exposure (High) |
| Exploit Status | PoC Available / Verified |
| CISA KEV Status | Not Listed |
The product exposes sensitive information to an actor who is not explicitly authorized to have access to that information.
A path traversal vulnerability (CWE-22) in Contao CMS allows unauthenticated remote attackers to bypass directory boundary restrictions in ImagesController and access files within the project directory.
Contao Open Source CMS versions 4.0.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 contain a Cross-Site Request Forgery (CSRF) vulnerability in backend parameter handling. The `RequestTokenListener` component validates anti-CSRF tokens solely for HTTP POST requests, while GET-based declarative guards run only when an `act` parameter is present in the query string. Consequently, custom backend actions dispatched via alternative parameters such as `key=` can execute without CSRF token verification when triggered by an authenticated user.
Contao CMS versions 4.1.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 fail to validate form submission tokens and enforce rate limiting when processing activation email resend requests via HTTP POST, enabling resource exhaustion and account state enumeration.
An information disclosure vulnerability in Contao CMS allows unauthenticated site visitors to view protected page titles, URLs, and text excerpts through search queries when protected page indexing is disabled after previously being enabled.
In Vikunja prior to version 2.6.0, relation creation via the CalDAV endpoint fails to invoke the TaskRelation.CanCreate authorization check. This missing access control allows an authenticated user to establish unauthorized relationships and perform write operations against any task, provided its unique identifier (UID) is known.
A cross-project information disclosure vulnerability in Vikunja allows authenticated users with read access to one project to view private task details from unauthorized projects via subtask expansion parameters.