CVE-2026-72811: SiYuan SQL Injection Vulnerability

CRITICAL
Advisory Identifier: GHSA-q2vg-7qgx-x5fc
CVSS 10.0
CWE-89
Published
Advisory Summary

CVE-2026-72811 is a CRITICAL (CVSS 10.0) sql injection vulnerability (CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')) affecting SiYuan libraries in the Go ecosystem. The issue involves sql injection in backlink/mention search via unescaped stored and client input (publish mode): first-order (client keyword) and second-order (stored document title) breakout on read-write handle. Remediation is available by upgrading affected packages to version 0.0.0-20260723004839-1a5b3431d5ab.

CVE-2026-72811 at a Glance

CVE Identifier CVE-2026-72811
GHSA Identifier GHSA-q2vg-7qgx-x5fc
Severity CRITICAL
CVSS v3.1 Base Score 10.0
CWE Classification CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
Affected Product SiYuan
Package Ecosystem Go
Published Date
Last Updated

Security Impact

CVSS: 10.0

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Changed (S:C)
Confidentiality High (C:H)
Integrity High (I:H)
Availability None (A:N)

How to Fix CVE-2026-72811

To remediate this vulnerability, upgrade all affected SiYuan dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

github.com/siyuan-note/siyuan/kernel fixed: 0.0.0-20260723004839-1a5b3431d5ab
Upgrade github.com/siyuan-note/siyuan/kernel to 0.0.0-20260723004839-1a5b3431d5ab
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for github.com/siyuan-note/siyuan/kernel

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-72811, inspect your project dependencies for SiYuan:

inspect dependencies for github.com/siyuan-note/siyuan/kernel

Analyze the terminal output to locate any version of SiYuan in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.0.0-20260723004839-1a5b3431d5ab), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection'), where the product constructs all or part of an sql command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended sql command when it is sent to a downstream component. without sufficient removal or quoting of sql syntax in user-controllable inputs, the generated sql query can cause those inputs to be interpreted as sql instead of ordinary user data. In SiYuan, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

**CVE:** This vulnerability corresponds to [CVE-2026-72811](https://nvd.nist.gov/vuln/detail/CVE-2026-72811). ### Summary The backlink/mention search query (`kernel/model/backlink.go`) concatenates stored block metadata (title, name, alias, anchor text) and the client-supplied keyword into a SQL `MATCH`/search statement, escaping only the double-quote character (`"`) and not the single quote (`'`). A single quote in either the client keyword or in stored document metadata breaks out of the string literal. The query runs on the main read-write `siyuan.db` handle through a statement-stacking-capable driver. This yields two vectors: - **First-order:** a client-supplied keyword containing `'` injects directly. This path is reachable by an anonymous reader on the publish surface. - **Second-order:** a document whose title/name/alias contains `'` is stored safely (indexing uses parameterized inserts) but detonates when that stored value is later concatenated into the backlink query including on another user's kernel that has ingested the malicious document. ### Details **Storage is safe; reuse is not.** Indexing INSERTs (`kernel/sql/upsert.go`) are parameterized (`(?,?,…)` with bound arguments for `Name`/`Content`/`Markdown`/`IAL`), so malicious `.sy` content is stored intact and safely. The injection is in the *reuse* path: the backlink/mention MATCH query (`kernel/model/backlink.go`, around line 980) builds its condition by concatenating the stored title/name/alias/anchor and the client keyword, applying only `"`→escaping and not `'`. A `'` in either source terminates the literal and lands in SQL context. **Sink / handle.** The concatenated statement reaches `SelectBlocksRawStmtNoParse` → `query()` on the global read-write `siyuan.db` handle (DSN has no `mode=ro`/`_query_only`), driven by the vendored `88250/go-sqlite3` fork whose connection `query` loops over `;`-separated statements (stacking possible). Ceiling is arbitrary SQL cross-notebook read and write. **Route / auth tier.** The backlink/mention family (`getBacklink`, `getBacklink2`, `getBacklinkDoc`, `getBackmentionDoc`) is `CheckAuth`-only, so the first-order client-keyword vector is reachable by the publish `RoleReader` token and by the anonymous account when `Publish.Auth.Enable` is `false`. **Scope of the injection surface (confirmed the only second-order sink).** A sweep of the query paths that reuse stored content confirmed this is the sole injectable reuse sink: indexing INSERTs are parameterized, tag search uses `content LIKE ?` with pattern escaping, virtual refs use in-memory matching (no SQL), `IN(...)` joins use node-IDs/hex-hashes/ROWIDs (no quote surface), and the graph name/content filter escapes `'`. Only the backlink/mention MATCH path concatenates with `'` unescaped. ### Proof of Concept Reproduced on a local instance (SiYuan running locally, publish mode enabled on port 6808, publish Basic Auth disabled). Strictly non-destructive verification, a syntax-error probe and a stored-value observation; no UNION exfiltration, no write, no DDL. **First-order (client keyword), anonymous reader on port 6808:** ``` POST http://127.0.0.1:6808/api/ref/getBacklink2 {"id":"<block id>","k":"a'b","mk":""} ``` The keyword `a'b` reaches the concatenated `MATCH` condition and produces a SQL parse error, confirming the single quote breaks out of the literal and the client keyword lands in SQL context. **Second-order (stored title), setup via admin then observed anonymously:** A document whose title contains a single quote e.g. `("locked-doc")` style metadata is stored safely by the parameterized indexer, then appears at the exact unescaped position in the backlink query when that document participates in a backlink/mention lookup, breaking the query the same way. This demonstrates that stored document metadata detonates on reuse, independent of the client keyword. Verification was limited to the syntax-error probe and the stored-value position observation; no exfiltration or write statement was executed. Full reproduction detail available privately on request. ### Impact **First-order:** an anonymous reader (publish mode with auth disabled) or any publish `RoleReader` injects arbitrary SQL into the backlink/mention query via the keyword parameter, on the read-write main handle: cross-notebook read disclosure and, via statement stacking, write and `ATTACH`. This is the same anonymous-arbitrary-SQL severity as the search/embed injection findings, on a different sink. **Second-order:** a document whose title/name/alias contains injection content is stored safely but executes when that stored value is concatenated into the backlink query. This fires on any kernel that has ingested the malicious document for example via a shared or imported `.sy` file, sync, or an opened `.sy.zip`. The precondition here is content delivery into the victim workspace (not a direct anonymous request), so it is a distinct, delivery-dependent threat model from the first-order vector. Encrypted notebooks are out of scope; code execution is not reachable in the default build (no `load_extension`). **Distinctness from the other SQL findings:** this is a different sink (`backlink.go` MATCH query) from the `searchDocs` (`LIKE` keyword), `searchEmbedBlock` (verbatim stmt), and `getEmbedBlock` (`IN`-clause ID array) findings, and it is the only one with a second-order (stored-content) vector. A fix to any of those does not remediate this path. ### Suggested fix Parameterize the backlink/mention query bind the keyword and any stored metadata as placeholders rather than concatenating or escape `'` (and use `LIKE`-pattern escaping) consistently, matching the tag-search and graph-filter paths that already do so. The second-order vector specifically requires that stored metadata be bound rather than concatenated, since escaping at storage time is not the defense (storage is already safe); the fix must be at the query-construction site.

CVE-2026-72811 Affected SiYuan Versions

1 component(s)
Fixed Versions:
0.0.0-20260723004839-1a5b3431d5ab
Product / Package Ecosystem Affected Versions Fixed Version
github.com/siyuan-note/siyuan/kernel
Go
< 0.0.0-20260723004839-1a5b3431d5ab
0.0.0-20260723004839-1a5b3431d5ab

References

Frequently Asked Questions

What is CVE-2026-72811?
CVE-2026-72811 is a security vulnerability in SiYuan involving SQL injection in backlink/mention search via unescaped stored and client input (publish mode): first-order (client keyword) and second-order (stored document title) breakout on read-write handle under CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection').
Which SiYuan versions are affected?
Affected versions include releases prior to 0.0.0-20260723004839-1a5b3431d5ab across affected packages: github.com/siyuan-note/siyuan/kernel.
What version fixes CVE-2026-72811?
Upgrading to 0.0.0-20260723004839-1a5b3431d5ab (or the latest patched release for your respective branch) resolves the vulnerability.
Is github.com/siyuan-note/siyuan/kernel affected?
Yes, github.com/siyuan-note/siyuan/kernel is affected in releases prior to 0.0.0-20260723004839-1a5b3431d5ab. Upgrade your dependency to 0.0.0-20260723004839-1a5b3431d5ab or later.
What is the CVSS score of CVE-2026-72811?
CVE-2026-72811 has a CVSS v3.1 base score of 10.0 (CRITICAL) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N.
What CWE is associated with CVE-2026-72811?
CVE-2026-72811 is classified under CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') (The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.).
How can I check Go dependencies for CVE-2026-72811?
Run the dependency tree command: 'inspect dependencies for github.com/siyuan-note/siyuan/kernel'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-q2vg-7qgx-x5fc",
  "modified" : "2026-09-03T22:27:50Z",
  "published" : "2026-09-03T22:27:50Z",
  "aliases" : [ "CVE-2026-72811" ],
  "summary" : "SiYuan: SQL injection in backlink/mention search via unescaped stored and client input (publish mode): first-order (client keyword) and second-order (stored document title) breakout on read-write handle",
  "details" : "**CVE:** This vulnerability corresponds to [CVE-2026-72811](https://nvd.nist.gov/vuln/detail/CVE-2026-72811).\n\n### Summary\n\nThe backlink/mention search query (`kernel/model/backlink.go`) concatenates stored block metadata (title, name, alias, anchor text) and the client-supplied keyword into a SQL `MATCH`/search statement, escaping only the double-quote character (`\"`) and not the single quote (`'`). A single quote in either the client keyword or in stored document metadata breaks out of the string literal. The query runs on the main read-write `siyuan.db` handle through a statement-stacking-capable driver.\n\nThis yields two vectors:\n- **First-order:** a client-supplied keyword containing `'` injects directly. This path is reachable by an anonymous reader on the publish surface.\n- **Second-order:** a document whose title/name/alias contains `'` is stored safely (indexing uses parameterized inserts) but detonates when that stored value is later concatenated into the backlink query including on another user's kernel that has ingested the malicious document.\n\n### Details\n\n**Storage is safe; reuse is not.** Indexing INSERTs (`kernel/sql/upsert.go`) are parameterized (`(?,?,…)` with bound arguments for `Name`/`Content`/`Markdown`/`IAL`), so malicious `.sy` content is stored intact and safely. The injection is in the *reuse* path: the backlink/mention MATCH query (`kernel/model/backlink.go`, around line 980) builds its condition by concatenating the stored title/name/alias/anchor and the client keyword, applying only `\"`→escaping and not `'`. A `'` in either source terminates the literal and lands in SQL context.\n\n**Sink / handle.** The concatenated statement reaches `SelectBlocksRawStmtNoParse` → `query()` on the global read-write `siyuan.db` handle (DSN has no `mode=ro`/`_query_only`), driven by the vendored `88250/go-sqlite3` fork whose connection `query` loops over `;`-separated statements (stacking possible). Ceiling is arbitrary SQL cross-notebook read and write.\n\n**Route / auth tier.** The backlink/mention family (`getBacklink`, `getBacklink2`, `getBacklinkDoc`, `getBackmentionDoc`) is `CheckAuth`-only, so the first-order client-keyword vector is reachable by the publish `RoleReader` token and by the anonymous account when `Publish.Auth.Enable` is `false`.\n\n**Scope of the injection surface (confirmed the only second-order sink).** A sweep of the query paths that reuse stored content confirmed this is the sole injectable reuse sink: indexing INSERTs are parameterized, tag search uses `content LIKE ?` with pattern escaping, virtual refs use in-memory matching (no SQL), `IN(...)` joins use node-IDs/hex-hashes/ROWIDs (no quote surface), and the graph name/content filter escapes `'`. Only the backlink/mention MATCH path concatenates with `'` unescaped.\n\n### Proof of Concept\n\nReproduced on a local instance (SiYuan running locally, publish mode enabled on port 6808, publish Basic Auth disabled). Strictly non-destructive verification, a syntax-error probe and a stored-value observation; no UNION exfiltration, no write, no DDL.\n\n**First-order (client keyword), anonymous reader on port 6808:**\n```\nPOST http://127.0.0.1:6808/api/ref/getBacklink2\n{\"id\":\"<block id>\",\"k\":\"a'b\",\"mk\":\"\"}\n```\nThe keyword `a'b` reaches the concatenated `MATCH` condition and produces a SQL parse error, confirming the single quote breaks out of the literal and the client keyword lands in SQL context.\n\n**Second-order (stored title), setup via admin then observed anonymously:**\nA document whose title contains a single quote e.g. `(\"locked-doc\")` style metadata is stored safely by the parameterized indexer, then appears at the exact unescaped position in the backlink query when that document participates in a backlink/mention lookup, breaking the query the same way. This demonstrates that stored document metadata detonates on reuse, independent of the client keyword.\n\nVerification was limited to the syntax-error probe and the stored-value position observation; no exfiltration or write statement was executed. Full reproduction detail available privately on request.\n\n### Impact\n\n**First-order:** an anonymous reader (publish mode with auth disabled) or any publish `RoleReader` injects arbitrary SQL into the backlink/mention query via the keyword parameter, on the read-write main handle: cross-notebook read disclosure and, via statement stacking, write and `ATTACH`. This is the same anonymous-arbitrary-SQL severity as the search/embed injection findings, on a different sink.\n\n**Second-order:** a document whose title/name/alias contains injection content is stored safely but executes when that stored value is concatenated into the backlink query. This fires on any kernel that has ingested the malicious document for example via a shared or imported `.sy` file, sync, or an opened `.sy.zip`. The precondition here is content delivery into the victim workspace (not a direct anonymous request), so it is a distinct, delivery-dependent threat model from the first-order vector.\n\nEncrypted notebooks are out of scope; code execution is not reachable in the default build (no `load_extension`).\n\n**Distinctness from the other SQL findings:** this is a different sink (`backlink.go` MATCH query) from the `searchDocs` (`LIKE` keyword), `searchEmbedBlock` (verbatim stmt), and `getEmbedBlock` (`IN`-clause ID array) findings, and it is the only one with a second-order (stored-content) vector. A fix to any of those does not remediate this path.\n\n### Suggested fix\n\nParameterize the backlink/mention query bind the keyword and any stored metadata as placeholders rather than concatenating or escape `'` (and use `LIKE`-pattern escaping) consistently, matching the tag-search and graph-filter paths that already do so. The second-order vector specifically requires that stored metadata be bound rather than concatenated, since escaping at storage time is not the defense (storage is already safe); the fix must be at the query-construction site.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Go",
      "name" : "github.com/siyuan-note/siyuan/kernel"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "0.0.0-20260723004839-1a5b3431d5ab"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/siyuan-note/siyuan/security/advisories/GHSA-q2vg-7qgx-x5fc"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-72811"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/siyuan-note/siyuan/commit/1a5b3431d5ab3036b19c1cc79486fedd6906fb57"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/siyuan-note/siyuan"
  }, {
    "type" : "WEB",
    "url" : "https://www.vulncheck.com/advisories/siyuan-before-sql-injection-via-backlink-search"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-89" ],
    "severity" : "CRITICAL",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-09-03T22:27:50Z",
    "nvd_published_at" : null
  }
}