CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-72796

CVE-2026-72796: Access Control Bypass via Static Routes in SiYuan

Amit Schendel
Amit Schendel
Senior Security Researcher

Sep 4, 2026·8 min read·16 visits

Executive Summary (TL;DR)

Inconsistent authorization controls in SiYuan prior to v3.7.4 permitted low-privilege or anonymous readers to bypass REST API security filters and download sensitive templates, snippets, widgets, and ZIP backups by accessing their static routes directly.

A detailed technical breakdown of CVE-2026-72796 (GHSA-fgmr-7w36-9qfq), an access control bypass vulnerability in the SiYuan personal knowledge management system. Prior to version 3.7.4, inconsistent authorization checks between dynamic API endpoints and static file routes allowed authenticated low-privilege readers or anonymous public users to read sensitive files, templates, snippets, and export directories.

Vulnerability Overview

SiYuan is a privacy-first, self-hosted personal knowledge management system that utilizes a local-first architecture while providing web-facing components for remote access and publishing. Prior to version 3.7.4, the application's backend server suffered from an authorization inconsistency in its routing logic. While dynamic REST API endpoints were protected by rigorous, role-based access control filters, static-file route groups bypassed these fine-grained authorization policies.

This flaw is classified under CWE-862 (Missing Authorization). The system exposed several sensitive static asset directories directly via the Gin Web Framework's static routing engine. Because these routes only verified the presence of basic authentication or a reader token, low-privilege readers and anonymous users could access administrative folders. This allowed the unauthorized disclosure of document templates, customized widgets, snippet files, and static export archives.

The attack surface is exposed via the web interface of any network-accessible SiYuan instance. An attacker with a valid low-privilege reader session, or an unauthenticated user if the instance is configured in public-publish mode, can bypass REST-level security restrictions. The impact is limited to confidentiality, enabling unauthorized retrieval of sensitive configuration parameters, custom script payloads, and potentially full database export backups.

The vendor mitigated this vulnerability in version 3.7.4 by implementing a dual-layer defensive control. First, sensitive static endpoints were restricted to verified administrators. Second, a dynamic reference-validation mechanism was introduced to parse Markdown Abstract Syntax Trees (ASTs) and dynamically authorize static assets only if they are actively referenced within a public document.

Root Cause Analysis

The SiYuan backend server uses the Gin Web Framework in Go to handle HTTP routing. The application registers dynamic API endpoints and static file directories within the same server initialization file, located at kernel/server/serve.go. In the vulnerable versions, the routing architecture created two separate paths for accessing workspace data: dynamic REST query endpoints and static file-serving groups.

The primary flaw lies in the inconsistent application of middleware across these routing paths. The REST API endpoints enforced strict, role-based authorization checks, validating that the requesting user possessed the administrator role before serving resources like templates or snippets. Conversely, static file route groups—such as /templates/*, /export/*, /widgets/*, /emojis/*, and /snippets/*—were registered using only the general model.CheckAuth middleware.

The model.CheckAuth middleware is designed to verify that the requesting client possesses a valid session, token, or cookie. However, in anonymous public-sharing or reader mode, this middleware considers low-privilege readers as authorized entities. Because the static route configuration mapped these entire directories to the file system under model.CheckAuth, the application failed to verify if the requesting entity had the specific administrator privileges required to access the underlying directories.

In addition to the missing authorization controls, the registration of these static routes lacked robust path-traversal validation. For example, the handler for /snippets/ utilized naive concatenation with filepath.Join and performed simple substring validation. While the system attempted to prevent directory traversal, it lacked central normalization, creating risk when handling complex URLs or symbolic links within the data directory.

Code Analysis

In versions prior to 3.7.4, the routing configuration in kernel/server/serve.go did not include administrative verification checks for static resource groups. The following code snippet illustrates the insecure configuration where the entire templates and widgets directories were exposed using Gin's standard static router grouping:

// Pre-patch code in kernel/server/serve.go
func serveWidgets(ginServer *gin.Engine) {
    // Insecure: only verifies basic auth, exposing all widgets
    widgets := ginServer.Group("/widgets/", model.CheckAuth)
    widgets.Static("", filepath.Join(util.DataDir, "widgets"))
}
 
func serveTemplates(ginServer *gin.Engine) {
    // Insecure: exposes all user-defined templates without admin verification
    templates := ginServer.Group("/templates/", model.CheckAuth)
    templates.Static("", filepath.Join(util.DataDir, "templates"))
}

The patch in commit 34be6c0bb0739d5b8e99ecc0cbfb474abb16230d introduces strict route separation and implements custom static handlers. In the patched code, access to sensitive templates and exports is strictly bound to administrative accounts, while a reference-checking mechanism secures widgets:

// Patched code in kernel/server/serve.go
func serveTemplates(ginServer *gin.Engine) {
    // Secure: admin-only check is now enforced on templates
    templates := ginServer.Group("/templates/", model.CheckAuth, model.CheckAdminRole)
    registerStaticFileHandlers(templates, filepath.Join(util.DataDir, "templates"), true, nil)
}

The custom handler function registerStaticFileHandlers replaces direct Gin file mapping. It enforces normalization of path requests through cleanStaticRelativePath, which filters out malicious traversal components prior to executing any file system read operation:

func cleanStaticRelativePath(requestPath string) (string, bool) {
    requestPath = strings.TrimPrefix(requestPath, "/")
    relativePath := filepath.Clean(filepath.FromSlash(requestPath))
    // Prevent directory traversal and escape sequences
    if filepath.IsAbs(relativePath) || filepath.VolumeName(relativePath) != "" ||
        relativePath == ".." || strings.HasPrefix(relativePath, ".."+string(os.PathSeparator)) {
        return "", false
    }
    return relativePath, true
}

The implementation of the cleanStaticRelativePath function combined with model.CheckAdminRole effectively remediates both directory traversal risks and the access control bypass on templates. For standard assets like emojis or widgets that must remain readable by guests, the patch implements a dynamic validation filter discussed in the mitigation section.

Exploitation

To exploit this vulnerability, an attacker must first establish a network connection to the target SiYuan web interface. The exploit does not require administrator privileges. Depending on the server configuration, the threat actor needs either a low-privilege reader token (if the server requires basic authentication) or zero authentication (if the instance is running in anonymous public-publish mode).

The attack relies on requesting static paths directly rather than querying the REST API endpoints. An administrator might block a regular reader from retrieving document templates via the standard API interface. However, the attacker bypasses this restriction by making a direct GET request targeting the static directory alias, for instance:

curl -i -H "Authorization: Token <low_privilege_reader_token>" \
     "http://siyuan-target.local:6806/templates/confidential-template.md"

Because the server did not validate whether the requested resource was linked to a public page, an attacker can brute-force common names of templates, custom snippets, and widgets. If an administrator previously exported the workspace database, the resulting file is saved in the static export directory. The attacker can download the export file by predicting or guessing its name, bypassing administrative REST controls:

curl -O "http://siyuan-target.local:6806/export/workspace_backup.zip"

Impact Assessment

The primary consequence of this vulnerability is the unauthorized disclosure of sensitive data. Because templates, export directories, and snippets can contain proprietary system configurations, API keys, or private notes, exposing these directories results in a serious breach of confidentiality. An attacker cannot use this vulnerability to write or modify server files, preserving the integrity of the data store.

In the context of CVSS v3.1, this vulnerability achieves a base score of 5.8 (Medium), with a vector of CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N. The scope parameter is marked as Changed (S:C) because the path-based authorization bypass permits transition from the restricted application-level sandbox directly to raw filesystem asset directories.

Currently, this vulnerability has an EPSS score of 0.00257 (0.26%), indicating a low overall probability of exploitation in wild campaigns within a 30-day window. It is not currently listed in CISA's Known Exploited Vulnerabilities (KEV) catalog, nor is it associated with known active ransomware frameworks. However, the ease of replication using single-line HTTP requests highlights the risk to self-hosted instances exposed directly to the public internet.

Remediation and Mitigation

The definitive remediation for CVE-2026-72796 is upgrading the SiYuan application to version 3.7.4 or later. In version 3.7.4, the developers refactored the routing subsystem to require model.CheckAdminRole on all sensitive directories including /templates/ and /export/. For containerized deployments, administrators should update their Docker configurations to fetch the latest official image tag.

For static directories that must remain accessible to public readers (such as /widgets/ and /emojis/), the vendor implemented a dynamic reference-validation mechanism. This engine parses the Markdown Abstract Syntax Tree (AST) of all published documents using the Lute engine. It extracts active widget and emoji references, dynamically adding them to a whitelist cache. When a reader requests a static widget, the server checks if that widget is in the whitelist, returning 403 Forbidden if it is not actively referenced.

If upgrading immediately is not feasible, administrators must reduce the exposed attack surface through configuration hardening. First, disable public publish mode and restrict the instance behind an authentication proxy or a private network segment. Second, manually inspect and clean the temp/export directory located in the application's workspace path to ensure no historical exports or sensitive zip archives remain readable on disk.

Technical Appendix

CVSS Score
5.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N

Affected Systems

SiYuan Personal Knowledge Management System
AttributeDetail
CWE IDCWE-862
Attack VectorNetwork
CVSS Score5.8 (Medium)
EPSS Score0.00257 (17.14th percentile)
ImpactConfidentiality
Exploit StatusProof-of-Concept
KEV StatusNot Listed
CWE-862
Missing Authorization

Vulnerability Timeline

Official patch committed to repository
2026-07-25
GitHub Security Advisory GHSA-fgmr-7w36-9qfq published
2026-08-12
CVE-2026-72796 assigned and published
2026-08-12

References & Sources

  • [1]GitHub Security Advisory GHSA-fgmr-7w36-9qfq
  • [2]SiYuan Fix Commit 34be6c0

More Reports

•2 minutes ago•CVE-2026-109619
9.2

CVE-2026-109619: Remote Code Execution in PHP Core via Stale Global State Memory Corruption (PHP2Shell)

CVE-2026-109619 (PHP2Shell) is a critical Use-After-Free vulnerability in the core PHP engine caused by improper global state cleanup during out-of-memory exception handling across persistent worker requests.

Alon Barad
Alon Barad
1 views•6 min read
•5 minutes ago•CVE-2026-113721
4.5

CVE-2026-113721: Unsafe Link Resolution in virtualenv File Generation

In Python virtualenv prior to version 21.14.9, activation script generators and configuration writers use Path.exists() before writing files. Because Path.exists() resolves symbolic links, it returns False for dangling symlinks. Consequently, virtualenv skips unlinking pre-planted symbolic links or hard links, writing data directly to target locations outside the intended virtual environment directory.

Amit Schendel
Amit Schendel
1 views•5 min read
•9 days ago•CVE-2026-87697
8.8

CVE-2026-87697: Untrusted Deserialization in .NET PresentationCore Clipboard Handling

A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.

Alon Barad
Alon Barad
31 views•5 min read
•9 days ago•CVE-2026-70007
8.8

CVE-2026-70007: Out-of-Bounds Write Vulnerability in .NET Framework and WPF Subsystem

An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.

Amit Schendel
Amit Schendel
19 views•6 min read
•10 days ago•CVE-2026-70186
7.5

CVE-2026-70186: ASP.NET Core Denial of Service Vulnerability via Framework Deadlock

ASP.NET Core contains a thread deadlock vulnerability (CWE-833) that allows an unauthenticated remote attacker to cause a denial of service over the network by exhausting server thread pool resources.

Amit Schendel
Amit Schendel
18 views•5 min read
•10 days ago•CVE-2026-70035
8.8

CVE-2026-70035: Insecure Deserialization Remote Code Execution in Microsoft .NET Framework and .NET Runtime

CVE-2026-70035 is a high-severity Remote Code Execution (RCE) vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio caused by improper handling during the deserialization of untrusted data (CWE-502). An unauthenticated attacker can execute arbitrary code within the context of the affected process by delivering a crafted serialized payload.

Amit Schendel
Amit Schendel
24 views•6 min read