GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration

GHSA-MFRJ-V65R-979C

Vulnerability from github – Published: 2026-09-04 20:58 – Updated: 2026-09-04 20:58
VLAI
Summary
SiYuan: Publish-access filter on renderAttributeView leaves related-database content unfiltered and fails open on non-block first columns
Details

CVE: This vulnerability corresponds to CVE-2026-72798.

Summary

renderAttributeView correctly applies the reader publish-access filter, but the filter's row-accessibility decision is keyed solely to the row's first cell, and it never inspects the remaining cells' values. Relation and Rollup cells carry mirrored content from a different database, so a row belonging to a published database can hand an anonymous reader the contents of a related database whose host document is hidden, publish-forbidden, or password-protected. Separately, when the first column is not a block value the accessibility check is skipped entirely and the row is returned unchecked.

Note:

This is distinct from the previously reported password-tier omission in the same function that concerns the row's own primary block, whereas these two defects concern (a) other cells' related-database content, which no row-level check covers and (b) rows where the first cell is not a block at all. A fix to the row-drop condition alone would close neither.

Details

renderAttributeView applies the filter (kernel/api/av.go:68):

retDataMap["view"] = model.FilterViewByPublishAccess(c, publishAccess, retDataMap["view"].(av.Viewable))

Inside FilterViewByPublishAccess (kernel/model/publish_access.go):

if row.Cells[0].Value.Block != nil {
    bt = treenode.GetBlockTree(row.Cells[0].Value.Block.ID)
}
if bt != nil {
    if !CheckPathAccessableByPublishIgnore(bt.BoxID, bt.Path, publishIgnore) {
        row = nil   // drop
    }
}
// every other cell in the row is returned as-is

(a) Relation and Rollup cells leak the related database. These value types carry mirrored content, not just references:

type ValueRelation struct { BlockIDs []string; Contents []*Value }
type ValueRollup   struct { Contents []*Value }

The render pipeline populates them from a different attribute view e.g. kernel/model/attribute_view.go:2731:

v.GroupVal.Relation.Contents = []*av.Value{ relationDestAv.GetBlockValue(groupValue) }

relationDestAv is a separate database that may live in a hidden, publish-forbidden, or password-protected document. When a published database's row survives the filter (because its column-0 document is public), its Relation and Rollup columns return the related, non-published database's content block text, titles, and mirrored column values. FilterViewByPublishAccess performs no publish-access evaluation on Relation.Contents or Rollup.Contents.

(b) Fail-open when column 0 is not a block. bt is assigned only when row.Cells[0].Value.Block != nil. If the first column is a non-block type (Relation, Text, …) or the row is detached, bt remains nil, the if bt != nil guard is skipped, and the row is returned with no accessibility check at all. Column order is user-reorderable, so any database whose first column is not the document block bypasses row filtering entirely.

Verified at origin/master (eef105683).

Proof of Concept

Precondition: publish mode enabled (default port 6808); anonymous when Publish.Auth.Enable is false. Two databases: DB-A hosted in a published document, DB-B hosted in a publish-forbidden or password-protected document, with a Relation column in DB-A pointing at DB-B and containing a distinctive marker value.

(a) Related-database content disclosure:

POST http://127.0.0.1:6808/api/av/renderAttributeView
{"id":"<DB_A_AV_ID>"}

Rows of DB-A are returned (correctly, since its host document is public), and their Relation/Rollup cell Contents include DB-B's block text and mirrored column values, despite DB-B's host document being excluded from publishing.

(b) Fail-open row: Reorder DB-A so its first column is a non-block type (or use a detached row), mark its host document publish-forbidden, and request the same endpoint the row is returned without any accessibility evaluation.

Verification status: both defects are confirmed by code inspection at origin/master. A live demonstration requires a build from HEAD with two linked databases; available on request.

Impact

An anonymous reader (publish mode with auth disabled) or any publish RoleReader can read content from databases whose host documents are hidden, publish-forbidden, or password-protected, by requesting a published database that relates to them. Because relation graphs are commonly used to link a public index to private detail records, this exposes exactly the data the publish boundary is meant to withhold. The fail-open path additionally returns rows with no accessibility check whenever the first column is not a block value, which is a user-controlled layout property. Confidentiality-only.

Suggested fix

In FilterViewByPublishAccess: 1. For each retained row, evaluate every Relation.Contents and Rollup.Contents entry against CheckBlockIdAccessableByPublishAccess (including the publish-password tier) and drop or mask entries that fail. 2. Fail closed: when row.Cells[0] has no accessible block (Value.Block == nil or bt == nil), drop the row rather than returning it unchecked.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/siyuan-note/siyuan/kernel"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.0.0-20260724121519-426991d155c0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-72798"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-862"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-04T20:58:04Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "**CVE:** This vulnerability corresponds to [CVE-2026-72798](https://nvd.nist.gov/vuln/detail/CVE-2026-72798).\n\n### Summary\n\n`renderAttributeView` correctly applies the reader publish-access filter, but the filter\u0027s row-accessibility decision is keyed solely to the row\u0027s **first cell**, and it never inspects the remaining cells\u0027 values. Relation and Rollup cells carry mirrored content from a *different* database, so a row belonging to a published database can hand an anonymous reader the contents of a related database whose host document is hidden, publish-forbidden, or password-protected. Separately, when the first column is not a block value the accessibility check is skipped entirely and the row is returned unchecked.\n\n### Note:\n\nThis is distinct from the previously reported password-tier omission in the same function that concerns the row\u0027s own primary block, whereas these two defects concern (a) other cells\u0027 related-database content, which no row-level check covers and (b) rows where the first cell is not a block at all. A fix to the row-drop condition alone would close neither.\n\n### Details\n\n`renderAttributeView` applies the filter (`kernel/api/av.go:68`):\n```go\nretDataMap[\"view\"] = model.FilterViewByPublishAccess(c, publishAccess, retDataMap[\"view\"].(av.Viewable))\n```\n\nInside `FilterViewByPublishAccess` (`kernel/model/publish_access.go`):\n```go\nif row.Cells[0].Value.Block != nil {\n    bt = treenode.GetBlockTree(row.Cells[0].Value.Block.ID)\n}\nif bt != nil {\n    if !CheckPathAccessableByPublishIgnore(bt.BoxID, bt.Path, publishIgnore) {\n        row = nil   // drop\n    }\n}\n// every other cell in the row is returned as-is\n```\n\n**(a) Relation and Rollup cells leak the related database.** These value types carry mirrored content, not just references:\n```go\ntype ValueRelation struct { BlockIDs []string; Contents []*Value }\ntype ValueRollup   struct { Contents []*Value }\n```\nThe render pipeline populates them from a different attribute view e.g. `kernel/model/attribute_view.go:2731`:\n```go\nv.GroupVal.Relation.Contents = []*av.Value{ relationDestAv.GetBlockValue(groupValue) }\n```\n`relationDestAv` is a separate database that may live in a hidden, publish-forbidden, or password-protected document. When a published database\u0027s row survives the filter (because its column-0 document is public), its Relation and Rollup columns return the related, non-published database\u0027s content block text, titles, and mirrored column values. `FilterViewByPublishAccess` performs no publish-access evaluation on `Relation.Contents` or `Rollup.Contents`.\n\n**(b) Fail-open when column 0 is not a block.** `bt` is assigned only when `row.Cells[0].Value.Block != nil`. If the first column is a non-block type (Relation, Text, \u2026) or the row is detached, `bt` remains `nil`, the `if bt != nil` guard is skipped, and the row is returned with no accessibility check at all. Column order is user-reorderable, so any database whose first column is not the document block bypasses row filtering entirely.\n\nVerified at `origin/master` (`eef105683`).\n\n### Proof of Concept\n\nPrecondition: publish mode enabled (default port 6808); anonymous when `Publish.Auth.Enable` is `false`. Two databases: **DB-A** hosted in a published document, **DB-B** hosted in a publish-forbidden or password-protected document, with a Relation column in DB-A pointing at DB-B and containing a distinctive marker value.\n\n**(a) Related-database content disclosure:**\n```\nPOST http://127.0.0.1:6808/api/av/renderAttributeView\n{\"id\":\"\u003cDB_A_AV_ID\u003e\"}\n```\nRows of DB-A are returned (correctly, since its host document is public), and their Relation/Rollup cell `Contents` include DB-B\u0027s block text and mirrored column values, despite DB-B\u0027s host document being excluded from publishing.\n\n**(b) Fail-open row:**\nReorder DB-A so its first column is a non-block type (or use a detached row), mark its host document publish-forbidden, and request the same endpoint the row is returned without any accessibility evaluation.\n\n*Verification status:* both defects are confirmed by code inspection at `origin/master`. A live demonstration requires a build from HEAD with two linked databases; available on request.\n\n### Impact\n\nAn anonymous reader (publish mode with auth disabled) or any publish `RoleReader` can read content from databases whose host documents are hidden, publish-forbidden, or password-protected, by requesting a *published* database that relates to them. Because relation graphs are commonly used to link a public index to private detail records, this exposes exactly the data the publish boundary is meant to withhold. The fail-open path additionally returns rows with no accessibility check whenever the first column is not a block value, which is a user-controlled layout property. Confidentiality-only.\n\n### Suggested fix\n\nIn `FilterViewByPublishAccess`:\n1. For each retained row, evaluate every `Relation.Contents` and `Rollup.Contents` entry against `CheckBlockIdAccessableByPublishAccess` (including the publish-password tier) and drop or mask entries that fail.\n2. Fail closed: when `row.Cells[0]` has no accessible block (`Value.Block == nil` or `bt == nil`), drop the row rather than returning it unchecked.",
  "id": "GHSA-mfrj-v65r-979c",
  "modified": "2026-09-04T20:58:04Z",
  "published": "2026-09-04T20:58:04Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/siyuan-note/siyuan/security/advisories/GHSA-mfrj-v65r-979c"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-72798"
    },
    {
      "type": "WEB",
      "url": "https://github.com/siyuan-note/siyuan/commit/426991d155c0c7c3a9e71badd6761eddfa8aad5b"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/siyuan-note/siyuan"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/siyuan-before-information-disclosure-via-renderattributeview"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "SiYuan: Publish-access filter on renderAttributeView leaves related-database content unfiltered and fails open on non-block first columns"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…