Search: ge.call
2,389 threats
Most recently published first
| Severity | CVSS | Signals | Threat | Source | Published | Score and star |
|---|---|---|---|---|---|---|
| Medium | 5.3 | EPSS 0.2% | CVE-2026-41337OpenClaw · Voice-call Plivo replay mutates in-process callback origin before replay rejection Medium5.3EPSS 0.2%GCVE DatabaseCVE-2026-41337 CVE-2026-41337 is a vulnerability in the openclaw-cli package where a voice-call Plivo replay can mutate the in-process callback origin before the replay is rejected. This issue affects versions from 2026.1.29 up to but not including 2026.3.31. The vulnerability has a medium severity with a CVSS score of 5.3. A fix is available in version 2026.3.31 and later. | GCVE Database | ||
| High | 8.2 | EPSS 0.1% | High8.2EPSS 0.1%GCVE DatabaseCVE-2026-41395 OpenClaw CLI's Plivo V3 webhook replay key generation used the raw verification URL without sorting query parameters, allowing attackers to replay signed webhook events by reordering query parameters. This flaw was fixed in version 2026.3.28 by canonicalizing the replay key. | GCVE Database | ||
| High | 7.5 | EPSS 0.4% | High7.5EPSS 0.4%GCVE DatabaseCVE-2026-42437 A vulnerability in the openclaw-cli package versions 2026.4.9 up to but not including 2026.4.10 allows the voice-call realtime WebSocket to accept oversized frames. This can lead to a remote availability impact by potentially disrupting service. The issue is fixed in version 2026.4.10 and later. | GCVE Database | ||
| Medium | 5.3 | EPSS 0.2% | Medium5.3EPSS 0.2%GCVE DatabaseCVE-2026-53808 A vulnerability in the OpenClaw CLI Skill Workshop apply flow allows an agent tool call to override a pending approval state, applying changes prematurely. This affects versions from 2026.1.29 up to but not including 2026.5.6. The issue does not alter the trusted-operator model but could impact configurations where lower-trust inputs reach the affected path. The vulnerability has a medium severity with a CVSS score of 5.3. | GCVE Database | ||
| Medium | 4.3 | EPSS 0.2% | Medium4.3EPSS 0.2%GCVE DatabaseCVE-2026-53845 A vulnerability in OpenClaw CLI allows skill-command dispatch to skip before-tool-call hooks, potentially bypassing hook-based auditing or policy enforcement. This affects versions from 2026.1.29 up to but not including 2026.5.6. The issue does not alter the trusted-operator model but may impact security depending on configuration and input trust levels. A patch is available in version 2026.5.6. Users are advised to avoid relying solely on hook enforcement for skill commands until patched and to apply general hardening measures such as restricting allowlists and disabling the affected feature if not needed. | GCVE Database | ||
| Medium | 4.3 | EPSS 0.3% | CVE-2026-42282n8n-MCP · Sensitive MCP tool-call arguments logged on authenticated requests in HTTP mode Medium4.3EPSS 0.3%GCVE DatabaseCVE-2026-42282 n8n-mcp versions 2.14.1 up to but not including 2.47.13 running in HTTP transport mode log sensitive tool-call arguments including credential material such as bearer tokens, OAuth credentials, API keys, and webhook authentication headers. This logging occurs before any redaction, potentially exposing secrets in server logs accessible beyond the request trust boundary. The vulnerability requires authentication and is mitigated in stdio transport mode. A fix is available in version 2.47.13 that prevents logging sensitive values by summarizing arguments without recording raw data. | GCVE Database | ||
| Medium | 5.3 | EPSS 0.2% | CVE-2026-48817Starlette · Arbitrary HTTP method dispatched to `HTTPEndpoint` attributes via `getattr` Medium5.3EPSS 0.2%GCVE DatabaseCVE-2026-48817 CVE-2026-48817 is a vulnerability in Starlette's HTTPEndpoint where arbitrary HTTP methods can invoke unintended endpoint attributes. This occurs when an HTTPEndpoint subclass is registered without explicitly restricting allowed HTTP methods, allowing non-standard methods to call internal methods as handlers. The issue affects Starlette and frameworks built on it, such as FastAPI. The vulnerability is fixed in version 3.4.0. | GCVE Database | ||
| Medium | 6.9 | EPSS 0.3% | CVE-2026-73606siyuan · Insecure Direct Object Reference Medium6.9EPSS 0.3%CVE Database V5CVE-2026-73606 ### Summary `/api/block/getRefIDs` filters its results for reader roles through a helper that checks only the visibility tiers. The password tier is not checked, because the helper does not receive the request context and therefore cannot evaluate the publish auth cookie. A reader who has not entered a document's publish password learns that the document references a given block. A function ten lines away in the same file does perform the full check, on the same input type. ### Details **Route,** identical at `eef105683` (`kernel/api/router.go:235`) and dev `a7ae96ce` (`:245`): ```go ginServer.Handle("POST", "/api/block/getRefIDs", model.CheckAuth, getRefIDs) ``` No `CheckReadonly`, no `CheckAdminRole`. **The filter chain.** `getRefIDs` (`kernel/api/block.go:631`) checks `isEncryptedNotebookDeniedForPublish`, calls `model.GetBlockRefsInBox`, then for read-only roles: ```go publishIgnore := model.GetInvisiblePublishAccess(publishAccess) refDefs, originalRefBlockIDs = model.FilterRefDefsByPublishIgnore(publishIgnore, refDefs) ``` `FilterRefDefsByPublishIgnore` (`kernel/model/publish_access.go:1324`) collects the reference and definition identifiers, resolves their block trees, and delegates the decision to `FilterBlockTreesByPublishIgnore` (`:1314`), whose entire body is: ```go for id, bt := range bts { if CheckPathAccessableByPublishIgnore(bt.BoxID, bt.Path, publishIgnore) { ret[id] = bt } } ``` Inside that helper, `CheckPublishAuthCookie`, `GetPathPasswordByPublishAccess`, `checkBlockTreeAccessableByPublishAccess` and `password` all appear zero times. **The complete check exists in the same file.** `kernel/model/publish_access.go:431`: ```go func checkBlockTreeAccessableByPublishAccess(c *gin.Context, publishAccess PublishAccess, bt *treenode.BlockTree) bool { if bt == nil || IsEncryptedBoxDeniedByPublishAccess(bt.BoxID) { return false } publishIgnore := filterDisablePublishAccess(publishAccess) passwordID, password := GetPathPasswordByPublishAccess(bt.BoxID, bt.Path, publishAccess) return CheckPathAccessableByPublishIgnore(bt.BoxID, bt.Path, publishIgnore) && (password == "" || CheckPublishAuthCookie(c, passwordID, password)) } ``` Same package, same file, same `*treenode.BlockTree` input. One takes the context and evaluates the password; the other does not receive it and structurally cannot. **Route-level contrast.** The adjacent `getChildBlocks` and `getTailChildBlocks` both carry `model.CheckAdminRole`. **Note on a prior assessment.** `getRefIDs` has been described as correctly filtered because it calls a publish-access filter. It does. The filter it calls covers the visibility tiers only. ### Proof of Concept Kernel 3.7.2, publish mode on port 6808, `Publish.Auth.Enable` false, anonymous client. A public document referenced from a second document whose publish tier was changed between runs. `getRefIDs` was called anonymously each time. | Tier of the referring document | Anonymous result | |---|---| | Public | reference returned (baseline) | | Password-protected | **reference still returned** | | Hidden | `[]`, filtered | | Forbidden | `[]`, filtered | The hidden and forbidden rows confirm the filter runs and works. The password-protected row is the defect. ### Impact An anonymous reader in publish mode, or any publish `RoleReader`, learns that a password-protected document contains a reference to a given block, without entering that document's password, and receives the block identifiers involved. Scoped precisely: the response carries identifiers only. `type RefDefs { RefID string; DefIDs []string }`, returned alongside `originalRefBlockIDs`, a map of identifier to identifier. There is no reference text, title or content. The disclosure is the existence of a relationship, plus identifiers usable as input to other endpoints. Confidentiality only. ### Suggested fix Thread `*gin.Context` into `FilterRefDefsByPublishIgnore` and `FilterBlockTreesByPublishIgnore`, and use `checkBlockTreeAccessableByPublishAccess` in place of the bare `CheckPathAccessableByPublishIgnore` call, so the password tier and the encrypted-box check are both applied. | CVE Database V5 | ||
| Critical | 9.1 | EPSS 0.3% | CVE-2026-15747Get iplayer: Mojolicious versions from 4.59 before 9.48 for Perl expose a stable representation of the session CSRF Critical9.1EPSS 0.3%GCVE DatabaseCVE-2026-15747 Mojolicious versions from 4.59 up to but not including 9.48 for Perl expose a stable session CSRF token representation that can be exploited via a BREACH compression oracle attack. The vulnerability arises because the _csrf_token method generates and caches a single token per session, returning the same token on every call, which is placed in a hidden csrf_token input field. When responses containing this token also include attacker-controlled input and are gzip-compressed, an attacker can use compression length differences to recover the CSRF token and bypass csrf_protect validation. This vulnerability is critical and has a CVSS score of 9.1. A patch is available in version 3.36_3. | GCVE Database | ||
| Medium | 6.3 | EPSS 0.6% | CVE-2026-50193Red Hat Security Advisory: Red Hat Lightspeed (formerly Insights) for Runtimes security update Medium6.3EPSS 0.6%GCVE DatabaseCVE-2026-50193 A vulnerability in jackson-databind affects versions from 2.0.0 up to but excluding 2.18.8, 2.21.4, and 3.1.4. The issue arises because the JDKFromStringDeserializer class eagerly resolves DNS names during deserialization of InetSocketAddress fields, potentially causing an attacker-controlled DNS query before application validation. The vulnerability is fixed by deferring DNS resolution until an explicit connect call. This flaw has a CVSS score of 7.5 and is rated as medium severity. | GCVE Database | ||
| High | 7.7 | EPSS 0.5% | CVE-2026-73498sooperset mcp-atlassian · Path Traversal High7.7EPSS 0.5%CVE Database V5CVE-2026-73498 MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian products (Confluence and Jira). Prior to 0.22.0, confluence_upload_attachment passes its client-supplied file_path directly to open(file_path, "rb") in src/mcp_atlassian/confluence/attachments.py through _upload_attachment_direct() without calling validate_safe_path. An authenticated MCP client can read any file accessible to the server process and exfiltrate it to Confluence as an attachment. If an AI agent can be induced to call the tool through untrusted content, the same flaw can disclose server environment variables such as CONFLUENCE_API_TOKEN and other credentials. This issue is fixed in version 0.22.0. | CVE Database V5 | ||
| High | 7.5 | EPSS 0.6% | CVE-2026-67579ash · Deserialization of Untrusted Data High7.5EPSS 0.6%CVE Database V5CVE-2026-67579 Deserialization of Untrusted Data vulnerability in ash-project ash allows an unauthenticated attacker to inject a filter expression through a forged keyset pagination cursor, resulting in SQL injection or code execution depending on the data layer. Read actions with keyset pagination decode the client-supplied page[:after] or page[:before] cursor in decode_values/2 in lib/ash/page/keyset.ex using non_executable_binary_to_term/2 with [:safe]. That guard blocks new atoms, funs, and ports, but not a struct built from atoms already interned in a running Ash application, so a decoded %Ash.Query.Call{} expression survives and is spliced into the keyset filter as a comparison value in do_filters/4 and evaluated. Because the cursor bypasses the Ash.Expr macro, the runtime never applies the private?/public? gate that would otherwise reject it. On AshPostgres the injected fragment is inlined into the SQL query; on the ETS and Simple data layers it is evaluated in-process as an arbitrary function call. This issue affects ash: from 1.17.0 before 3.31.3. | CVE Database V5 | ||
| High | 7.1 | EPSS 0.3% | CVE-2026-72809siyuan · Authentication Bypass by Spoofing High7.1EPSS 0.3%CVE Database V5CVE-2026-72809 **CVE:** This vulnerability corresponds to [CVE-2026-72809](https://nvd.nist.gov/vuln/detail/CVE-2026-72809). ### Summary The kernel's `CheckAuth` grants `RoleAdministrator` to any request whose `RemoteAddr` is loopback (`127.0.0.1`), for a specific set of endpoints, and these localhost bypasses sit **outside** the `accessAuthCode` gate so they apply even when an access auth code is configured. This is demonstrated live (Part A below). Separately, the fixed-port reverse proxy (`fixedport.go`) forwards requests to the kernel over loopback and injects no authentication token, and no `SetTrustedProxies` is configured, so gin does not derive the client address from forwarding headers. By code inspection, a request forwarded through this proxy would reach the kernel with `RemoteAddr = 127.0.0.1`. **If** the fixed-port proxy is bound to a network interface (via `NetworkServe`) and forwards remote requests to the kernel this way, the localhost bypass would grant a remote unauthenticated caller admin on those endpoints. This second step is established by reading the code but was **not reproduced end-to-end**, and I'm asking the maintainer to confirm the proxy's runtime forwarding behavior (Part B below). ### Details **Localhost-trust admin bypass (proven).** `CheckAuth` (`session.go:298-321`) contains localhost-only bypasses that key off `RemoteAddr` and grant `RoleAdministrator`. They sit outside the `accessAuthCode` gate i.e. they apply even when an access auth code is set and cover `/api/system/exit`, `getNetwork`, `getWorkspaceInfo`, `/assets/*`, and `/export/*`. **Fixed-port proxy behavior (code inspection).** `fixedport.go` is a plain reverse proxy that dials the kernel at `127.0.0.1` and injects no token unlike the publish proxy, which injects a `RoleReader` JWT. There is no `SetTrustedProxies` call, so gin does not rewrite `RemoteAddr` from `X-Forwarded-For`. On this reading, a request forwarded through the fixed-port proxy reaches the kernel with `RemoteAddr = 127.0.0.1`. **The composition (conditional).** If both hold at runtime, then: remote request → fixed-port proxy on a network interface → forwarded to kernel at `127.0.0.1` (no token) → kernel sees `RemoteAddr = 127.0.0.1` → localhost bypass grants admin for the endpoints above. I have proven the final link (localhost → admin) and read the code for the forwarding link, but have not confirmed at runtime that the fixed-port proxy is instantiated and forwards remote requests as loopback in a shipped configuration. **Distinct from the previously-dismissed localhost→admin observation.** That observation concerned the *publish* proxy path, where the injected `RoleReader` JWT causes `CheckAuth` to early-return before reaching the localhost bypasses. The fixed-port proxy injects no token, so a request through it would fall through to the `RemoteAddr`-keyed bypass instead. Different proxy, different code path. ### Proof of Concept **Part A: the localhost bypass grants admin without auth, outside the auth-code gate (demonstrated live).** On a local instance with an access auth code configured, the same no-token `getWorkspaceInfo` request returns different results depending on the source address the kernel sees: - From a non-loopback source (kernel sees a non-127.0.0.1 address): `HTTP 401`. - From `127.0.0.1` (kernel sees loopback): `{"code":0,"data":{"workspaceDir":"/siyuan/workspace",…}}` admin data, no auth, despite `accessAuthCode` being set. This confirms the localhost-trust bypass grants admin for these endpoints and is not gated by the access auth code. **Part B: remote → proxy → loopback (code inspection only; NOT reproduced).** By reading `fixedport.go`, the proxy dials `127.0.0.1`, injects no token, and no `SetTrustedProxies` is set. I was not able to reproduce this end-to-end: the `serve` CLI in the container image tested exposes only `--port` and `--accessAuthCode`, not a flag that instantiates the fixed-port proxy in the `NetworkServe`-on-a-non-default-port shape, so the remote→proxy→loopback chain was not exercised at runtime. I did not invoke the destructive `/api/system/exit` endpoint. **I'm asking the maintainer to confirm: under what conditions is the fixed-port proxy instantiated, does it bind a non-loopback interface under `NetworkServe`, and does it forward to the kernel preserving the client address or as loopback?** That determines whether Part A's bypass is remotely reachable. ### Impact **Confirmed (Part A):** on any deployment where a caller can cause the kernel to see a loopback `RemoteAddr`, the endpoints `/api/system/exit`, `getNetwork`, `getWorkspaceInfo`, `/assets/*`, and `/export/*` are reachable with admin rights without the access auth code i.e. the auth code does not protect these endpoints against a loopback-sourced caller. On its own this is a local/adjacent bypass of the access-code control for those endpoints. If the fixed-port proxy forwards remote requests to the kernel as loopback (to be confirmed by the ma | CVE Database V5 | ||
| High | 8.8 | EPSS 0.3% | CVE-2026-72807siyuan · SQL Injection High8.8EPSS 0.3%CVE Database V5CVE-2026-72807 **CVE:** This vulnerability corresponds to [CVE-2026-72807](https://nvd.nist.gov/vuln/detail/CVE-2026-72807). ### Summary Attribute-view (AV) template columns are live-evaluated on every render and expose the `queryBlocks` template function, which runs raw SQL on the read-write database handle (`SelectBlocksRawStmt`, using `?`→argument string substitution rather than parameter binding). AV mutations are admin-gated, so this is not directly reader-injectable but it is a second-order vector: an attacker distributes a SiYuan document or AV package whose template column contains `.action{queryBlocks "<arbitrary SQL>"}` when a victim imports the package and renders the AV, the attacker's SQL executes on the victim's kernel (read and, via statement stacking, write). ### Details Doc-level `{{…}}` templates are rendered at insert-time and become static, so they are not re-evaluated on reader view. The residual is AV template columns, which are live-evaluated at render. `queryBlocks` passes its argument to `SelectBlocksRawStmt` with `?`→arg string substitution, not a bound parameter, on the main read-write handle (`88250/go-sqlite3` fork, statement-stacking capable) so an attacker-controlled template argument becomes arbitrary SQL. The SSTI surface is otherwise hardened: `BuiltInTemplateFuncs` deletes `env`, `expandenv`, and `getHostByName` so there is no environment/host/file/exec SSTI. `queryBlocks`-to-SQL is the remaining live-evaluated sink. ### Proof of Concept An AV template column set to `.action{queryBlocks "<sql>"}` executes `<sql>` against the read-write handle when the AV is rendered. Delivered second-order: a shared/imported document or AV package carrying such a column runs the embedded SQL on any kernel that imports and renders it. ### Proof of Concept Reproduced on a live instance. **1. Host doc + AV (admin, 6806):** ``` POST /api/filetree/createDocWithMd {notebook, path:"/ssti-poc", markdown:"host"} → DOC POST /api/av/renderAttributeView {id:"<AV>"} # materializes the AV ``` **2. Plant the malicious template column (one performTransactions call):** ```json {"reqId":1,"session":"poc","transactions":[{"doOperations":[ {"action":"addAttrViewCol","avID":"<AV>","id":"<COL>","name":"tpl","type":"template"}, {"action":"updateAttrViewColTemplate","avID":"<AV>","id":"<COL>","type":"template", "data":".action{range queryBlocks \"SELECT * FROM blocks WHERE root_id='<PROTECTED_DOC_ID>'\"}.action{.Markdown} .action{end}"}, {"action":"insertAttrViewBlock","avID":"<AV>","isDetached":true} ]}]} ``` **3. Trigger (render evaluates the template):** ``` POST /api/av/renderAttributeView {id:"<AV>"} ``` Result: the template cell renders `## LockedSection TOP_SECRET…` the `queryBlocks` SQL executed and returned the password-protected document's content, arbitrary SQL via template reading across the publish/password boundary. `queryBlocks` uses `?`→arg string substitution (not parameterized), so UNION and stacked writes are also possible. Delivered second-order, the same column executes on any kernel that imports and renders the AV. ### Impact An attacker who gets a victim to import a crafted document/AV package and render it achieves arbitrary SQL execution on the victim's kernel cross-notebook read and via stacking, write. Precondition is content delivery plus render (import of an attacker-supplied package), which bounds severity to Medium. Not directly reachable by an anonymous reader (AV creation is admin-gated); the injection travels in stored/imported template content. ### Suggested fix Parameterize `queryBlocks` bind the argument rather than substituting it into the SQL string or restrict the template function set available in AV columns as was done for the doc-template functions. Treat imported template content as untrusted at render time. | CVE Database V5 | ||
| Medium | 6.9 | EPSS 0.3% | CVE-2026-72805siyuan · Missing Authorization Medium6.9EPSS 0.3%CVE Database V5CVE-2026-72805 **CVE:** This vulnerability corresponds to [CVE-2026-72805](https://nvd.nist.gov/vuln/detail/CVE-2026-72805). ### Summary Three block endpoints return document content snippets and metadata without any publish-access check, while their sibling `getBlockInfo` which returns comparable data does enforce one. All three are `CheckAuth`-only, so they are reachable by the publish `RoleReader` token and by the anonymous account when `Publish.Auth.Enable` is `false`. An anonymous reader supplying a block ID receives content and metadata belonging to publish-forbidden and password-protected documents. ### Details `getBlockInfo` (`kernel/api/block.go`) gates on the publish boundary: ```go if !checkBlockPublishAccess(c, id, ret) { return } ``` The following siblings in the same file perform no equivalent check: | Endpoint | Returns | Publish check | |---|---|---| | `getBlockInfo` | root/title/path metadata | `checkBlockPublishAccess`: present | | `getBlockBreadcrumb` | `BlockPath.Name` : root document title plus every ancestor block's content snippet | none | | `getRefText` | the block's reference/anchor text (document content) | none | | `getBlockTreeInfos` | root/title/path metadata for arbitrary block IDs | none | `getBlockBreadcrumb` returns the full ancestor chain including each ancestor block's content snippet, and `getRefText` returns block anchor text both are document content, not just metadata. `getBlockTreeInfos` returns root/title/path for any caller-supplied ID set via `model.GetBlockTreeInfosInBox(...)` with no gate. `getBlockBreadcrumb` and `getRefText` additionally accept a client-supplied notebook argument that routes to the `*InBox` variants, so the same unguarded path applies to encrypted-notebook reads while the notebook is unlocked. The correct primitive already exists in the codebase and is used by `getBlockInfo`; these three handlers simply do not call it. ### Proof of Concept Precondition: publish mode enabled (default port 6808); anonymous when `Publish.Auth.Enable` is `false`, otherwise any publish reader account. A document `D` is marked publish-forbidden (or password-protected) and contains a block `BLOCK_ID` under a heading with distinctive content. **Control: the gated sibling correctly refuses:** ``` POST http://127.0.0.1:6808/api/block/getBlockInfo {"id":"BLOCK_ID"} ``` Blocked by `checkBlockPublishAccess`. **Disclosure: the ungated siblings return the data anyway:** ``` POST http://127.0.0.1:6808/api/block/getBlockBreadcrumb {"id":"BLOCK_ID"} → ancestor chain including the forbidden document's title and ancestor block content snippets POST http://127.0.0.1:6808/api/block/getRefText {"id":"BLOCK_ID"} → the block's reference/anchor text (content of the forbidden document) POST http://127.0.0.1:6808/api/block/getBlockTreeInfos {"ids":["BLOCK_ID"]} → root ID, title, and path for the forbidden document ``` Verified by code inspection at `origin/master` (`eef10568`): `getBlockInfo` contains the `checkBlockPublishAccess` call; `getBlockBreadcrumb`, `getRefText`, and `getBlockTreeInfos` contain no publish-access, publish-ignore, or readonly-role check in their bodies. ### Impact An anonymous reader (publish mode with auth disabled) or any publish `RoleReader` can read, for documents explicitly excluded from publishing or protected by a publish password: - the document title and full ancestor chain, including ancestor block content snippets (`getBlockBreadcrumb`); - block reference/anchor text, i.e. document content (`getRefText`); - root ID, title, and path metadata for arbitrary block IDs (`getBlockTreeInfos`). Because `getBlockBreadcrumb` and `getRefText` accept a notebook argument routing to the `*InBox` variants, the same disclosure applies to encrypted notebooks while unlocked. Confidentiality-only; the precondition is a block ID, obtainable from other reader-reachable endpoints. ### Suggested fix Call `checkBlockPublishAccess` (as `getBlockInfo` does) in `getBlockBreadcrumb`, `getRefText`, and `getBlockTreeInfos` before returning data for `getBlockTreeInfos`, apply it per ID and drop unauthorized entries. Confirm the `*InBox` variants (`GetBlockRefTextInBox`, `BuildBlockBreadcrumbInBox`) enforce the same boundary so the notebook-argument path is covered. | CVE Database V5 | ||
| Critical | 9.2 | EPSS 0.4% | CVE-2026-72804siyuan · Information Exposure Critical9.2EPSS 0.4%CVE Database V5CVE-2026-72804 **CVE:** This vulnerability corresponds to [CVE-2026-72804](https://nvd.nist.gov/vuln/detail/CVE-2026-72804). ### Summary `getGraph` and `getLocalGraph` filter reader sessions against the *visibility* tier only and never check the publish password. Password-protected documents are `Visible = true`, so their graph nodes survive the filter and graph nodes are block-level and carry the block's actual content. An anonymous reader who has never supplied a document's password can therefore retrieve that document's per-block content and its reference/backlink topology. Both endpoints are `CheckAuth`-only, so they are reachable by the publish `RoleReader` token and by the anonymous account when `Publish.Auth.Enable` is `false`. ### Details Both handlers filter with the invisible-tier set only: ```go publishIgnore := model.GetInvisiblePublishAccess(publishAccess) // Visible tier ONLY nodes, links = model.FilterGraphByPublishIgnore(publishIgnore, nodes, links) ``` `FilterGraphByPublishIgnore` (`kernel/model/publish_access.go:849`) drops a node only when `!CheckPathAccessableByPublishIgnore(node.Box, node.Path, publishIgnore)`. There is no password evaluation anywhere in the graph code grepping `graph.go` for `CheckPublishAuthCookie` or `password` returns nothing. Because password-protected documents are `Visible = true`, their nodes pass the filter unchanged. **The nodes carry content, not just titles.** `genTreeNodes` emits one node per block, and `nodeTitleLabel` sets `node.Title = node.Label = block.Content` (`kernel/model/graph.go:673-678`). So each surviving node exposes the block's text. This is materially broader than the by-design listing behaviour: `listDocsByPath` intentionally exposes protected document *titles* (protected means "publicly visible, password required to access"), but the graph endpoints expose per-block *content* and the full link/reference topology, which listing never does. Verified at `origin/master`: `FilterGraphByPublishIgnore` contains only the `CheckPathAccessableByPublishIgnore` call; `graph.go` contains no password check; both routes are registered `CheckAuth` without `CheckAdminRole`. ### Proof of Concept Precondition: publish mode enabled (default port 6808); anonymous when `Publish.Auth.Enable` is `false`, otherwise any publish reader account. A document is marked **protected** (visible, password set) and contains blocks with distinctive content. No password is supplied in any request below. **Targeted: one protected document's content and reference structure:** ``` POST http://127.0.0.1:6808/api/graph/getLocalGraph {"id":"<PROTECTED_DOC_ID>"} ``` Returns nodes whose `Title`/`Label` contain the protected document's per-block content, plus its links/backlinks. **Workspace-wide: every protected document:** ``` POST http://127.0.0.1:6808/api/graph/getGraph {} ``` Returns block-level nodes for every protected document in the workspace, together with the complete link graph. **Control:** requesting the same document through the normal content path returns the password placeholder confirming the password gate is enforced elsewhere and omitted here. ### Impact An anonymous reader (publish mode with auth disabled) or any publish `RoleReader` can read the block-level content of every password-protected document in the workspace, plus the full reference/backlink topology, without ever supplying a password. This defeats the publish-password control for the graph subsystem. Confidentiality-only, no modification. ### Suggested fix Extend the graph filter to evaluate the password tier in addition to visibility: in `FilterGraphByPublishIgnore`, drop a node unless the document's publish password is unset or the caller presents a valid publish-auth cookie for it (`password == "" || CheckPublishAuthCookie(...)`), matching the sibling filters that enforce both tiers. Consider also excluding block content from node `Title`/`Label` for reader sessions, so the graph conveys structure without document text. | CVE Database V5 | ||
| Medium | 6.9 | EPSS 0.3% | CVE-2026-72803siyuan · Missing Authorization Medium6.9EPSS 0.3%CVE Database V5CVE-2026-72803 **CVE:** This vulnerability corresponds to [CVE-2026-72803](https://nvd.nist.gov/vuln/detail/CVE-2026-72803). ### Summary `POST /api/attr/getBlockAttrs` and `POST /api/attr/batchGetBlockAttrs` return a block's full attribute set (IAL) with no publish-access check. Both are `CheckAuth`-only, so they are reachable by the publish `RoleReader` token and by the anonymous account when `Publish.Auth.Enable` is `false`. An anonymous reader supplying a block ID receives the block's name, alias, memo, bookmark, tags, and every `custom-*` attribute including for blocks in publish-forbidden and password-protected documents. The batch variant accepts an ID list, making it a bulk extraction primitive. ### Details Neither handler applies a filter: ```go // /api/attr/getBlockAttrs (router line 301) ret.Data = sql.GetBlockAttrs(id) // /api/attr/batchGetBlockAttrs (router line 302) ret.Data = sql.BatchGetBlockAttrs(idList) ``` `sql.GetBlockAttrs` is a direct database read returning the block's entire IAL: `name`, `alias`, `memo`, `bookmark`, `tags`, and any `custom-*` key/value the user has set. Several of these are user-authored free text memos in particular are freeform notes attached to a block so this is document content, not merely structural metadata. `batchGetBlockAttrs` takes an arbitrary list of block IDs in a single request, so an attacker holding a set of block IDs can sweep attributes across the entire workspace in one call. **Guarded-sibling asymmetry.** The sibling metadata endpoint `getBlockInfo` calls `checkBlockPublishAccess(c, id, ret)` before returning; `getBlockAttrs` and `batchGetBlockAttrs` call nothing. Verified at `origin/master`: both handler bodies contain no publish-access, publish-ignore, or readonly-role check, and both routes are registered `CheckAuth` without `CheckAdminRole`. ### Proof of Concept Precondition: publish mode enabled (default port 6808); anonymous when `Publish.Auth.Enable` is `false`, otherwise any publish reader account. A document is marked publish-forbidden (or password-protected) and contains a block with a memo and a custom attribute set. **Single-block disclosure:** ``` POST http://127.0.0.1:6808/api/attr/getBlockAttrs {"id":"<BLOCK_ID_IN_PROTECTED_DOC>"} ``` Returns the block's IAL: `name`, `alias`, `memo`, `bookmark`, `tags`, and all `custom-*` values. **Bulk disclosure:** ``` POST http://127.0.0.1:6808/api/attr/batchGetBlockAttrs {"ids":["<ID1>","<ID2>","<ID3>"]} ``` Returns the attribute sets for every supplied ID in one response, with no per-ID authorization. **Control:** the sibling `getBlockInfo` with the same block ID is refused by `checkBlockPublishAccess`, confirming the boundary is enforced elsewhere and omitted here. ### Impact An anonymous reader (publish mode with auth disabled) or any publish `RoleReader` can read block attributes belonging to publish-forbidden and password-protected documents, including user-authored memos and arbitrary `custom-*` values. The batch endpoint turns this into a bulk primitive: given a set of block IDs, an attacker retrieves attributes across the whole workspace in a single request. Confidentiality-only. ### Suggested fix Call `checkBlockPublishAccess` in `getBlockAttrs` before returning, matching `getBlockInfo`. For `batchGetBlockAttrs`, apply the check per ID and drop unauthorized entries from the response rather than failing the whole batch. | CVE Database V5 | ||
| Medium | 6.9 | EPSS 0.3% | CVE-2026-72799siyuan · Missing Authorization Medium6.9EPSS 0.3%CVE Database V5CVE-2026-72799 **CVE:** This vulnerability corresponds to [CVE-2026-72799](https://nvd.nist.gov/vuln/detail/CVE-2026-72799). ### Summary Five filetree endpoints resolve arbitrary document IDs and paths with no publish-access check of any kind. All are `CheckAuth`-only, so they are reachable by the publish `RoleReader` token and by the anonymous account when `Publish.Auth.Enable` is `false`. An anonymous reader can map the complete private document tree every notebook, folder, and document title, and which notebook holds each document for documents marked hidden, password-protected, or publish-forbidden, and can resolve titles to document IDs. ### Details None of the following handlers invokes `IsReadOnlyRoleContext`, `CheckBlockIdAccessableByPublishAccess`, or `CheckPathAccessableByPublishIgnore`: | Endpoint | Returns | Discloses | |---|---|---| | `getFullHPathByID` (router 159) | `GetFullHPathByID(id)` | full title path including notebook, e.g. `/MySecretNotebook/Confidential/Q3 Layoffs Plan` | | `getHPathByID` (router 157) | `GetHPathByID(id)` | document-relative title path | | `getPathByID` (router 158) | `{path, notebook}` | which notebook a document lives in, plus its `.sy` storage path | | `getIDsByHPath` (router 160) | `GetIDsByHPath(path, notebook)` | title-path → document-ID enumeration | | `getHPathByPath` (router 155) | HPath from a storage path | title path from a storage path | Each accepts an arbitrary ID or HPath and resolves it identically for hidden, publish-forbidden, and password-protected documents. This enables two operations for an unauthenticated caller: 1. **Map the private document tree**: `getFullHPathByID` and `getPathByID` yield every notebook/folder/document title and its containing notebook. 2. **Resolve titles to IDs**: `getIDsByHPath` converts a known or guessed title path into document IDs, which are the required input for other block-read endpoints. Document titles and HPaths are precisely the block metadata that the project's block-metadata restriction (commit `ffde3b21e`) set out to protect; that change gated `getBlockInfo`, `getDocInfo`, and `getDocsInfo` but left this entire path-resolution family open. **Guarded-sibling asymmetry.** `getRecentDocs` (`FilterRecentDocsByPublishAccess`), `getCriteria` (`FilterCriteriaByPublishAccess`), and `getLocalStorage` (`FilterLocalStorageByPublishAccess`) all filter document references for reader sessions. The codebase clearly publish-scopes reader-visible metadata elsewhere; these five endpoints do not. Verified at `origin/master` (`eef105683`): all five handler bodies contain no publish-access call; the storage-family siblings contain their filters; all five routes are registered `CheckAuth` without `CheckAdminRole`. ### Proof of Concept Precondition: publish mode enabled (default port 6808); anonymous when `Publish.Auth.Enable` is `false`, otherwise any publish reader account. A document exists in a notebook marked publish-forbidden or password-protected. **Resolve a private document's full title path:** ``` POST http://127.0.0.1:6808/api/filetree/getFullHPathByID {"id":"<DOC_ID>"} → /MySecretNotebook/Confidential/Q3 Layoffs Plan ``` **Identify its notebook and storage path:** ``` POST http://127.0.0.1:6808/api/filetree/getPathByID {"id":"<DOC_ID>"} → {"path":"/....sy","notebook":"<BOX_ID>"} ``` **Enumerate IDs from a title path:** ``` POST http://127.0.0.1:6808/api/filetree/getIDsByHPath {"path":"/Confidential","notebook":"<BOX_ID>"} → document IDs under a folder the reader cannot otherwise access ``` Each returns data for documents excluded from publishing; no password or membership is required. ### Impact An anonymous reader (publish mode with auth disabled) or any publish `RoleReader` can enumerate the complete private document structure: notebook names, folder hierarchy, and document titles for content the administrator marked hidden, password-protected, or excluded from publishing. Document titles alone are frequently sensitive (project names, personnel actions, client identifiers). The ID-resolution direction additionally supplies valid document IDs, removing the "attacker must know an ID" precondition for other block-read endpoints. Confidentiality-only. ### Suggested fix For `IsReadOnlyRoleContext` sessions, gate each of the five handlers with `CheckBlockIdAccessableByPublishAccess` (or restrict resolution to publish-visible documents), mirroring the treatment already applied in `getRecentDocs`, `getCriteria`, and `getLocalStorage`. | CVE Database V5 | ||
| Critical | 9.2 | EPSS 0.3% | CVE-2026-72795siyuan · Missing Authorization Critical9.2EPSS 0.3%CVE Database V5CVE-2026-72795 **CVE:** This vulnerability corresponds to [CVE-2026-72795](https://nvd.nist.gov/vuln/detail/CVE-2026-72795). ### Summary `/api/block/getBlockDOMWithEmbed` and `/api/block/getBlockDOMsWithEmbed` gate only the *requested* block against publish access. The blocks pulled in by that block's embed (transclusion) query are inlined into the returned DOM with no publish-access check at all, so a reader who requests a legitimately-published block containing an embed query receives the content of every block that query matched including blocks in hidden, forbidden and password-protected documents. The dedicated embed endpoint `getEmbedBlock` filters these same results for reader roles. The DOM-with-embed path does not. ### Details | Item | Detail | |---|---| | Routes | `kernel/api/router.go:226` `POST /api/block/getBlockDOMWithEmbed` → `model.CheckAuth` → `getBlockDOMWithEmbed`; `:227` `POST /api/block/getBlockDOMsWithEmbed` → `model.CheckAuth` → `getBlockDOMsWithEmbed` | | Middleware | `CheckAuth` only — no `CheckReadonly`, no `CheckAdminRole` → reachable by the publish `RoleReader` token, and anonymously when `Publish.Auth.Enable` is `false` | | Guard present | Top-level requested block only. Singular: password + disable checks on the requested id. Plural: `filterBlockDOMsByPublishAccess` over the requested ids. | | Guard absent | The embedded blocks resolved from the query | | Exposed | Content HTML of every block matched by the embed query, regardless of that block's publish visibility or password tier | **The leak path.** `getBlockDOMWithEmbed` → `GetBlockDOMsWithEmbedInBox` → `resolveEmbedContentInBox` (`kernel/model/block.go:976`). That function walks the tree for `NodeBlockQueryEmbed`, extracts the embed SQL, executes `sql.SelectBlocksRawStmtInBox(stmt, ...)`, builds `embedContents` from each matched block's content HTML, and inlines the result via `SetIALAttr("embed-content", ...)`. `resolveEmbedContentInBox` takes no `publishAccess` parameter and contains no filtering: `FilterEmbedBlocks`, `CheckBlockIdAccessableByPublishAccess`, `CheckPathAccessable`, `publishAccess` and `IsReadOnlyRoleContext` all return zero matches in that function and its call path. The top-level gate therefore passes on the requested block, and the response body carries content the reader has no access to. Embed queries in published documents routinely span the entire workspace by design, dashboard documents, "all my TODOs" aggregations, tag or attribute rollups. The reader does not need to construct anything: requesting an already-published document that contains such an embed is sufficient. If the publish frontend renders embedded blocks through this endpoint, the disclosure occurs passively during normal viewing of any published document containing an embed block. **Guarded sibling.** `getEmbedBlock` (`kernel/api/router.go:212`), which is also reader-reachable and returns embed query results, applies `model.FilterEmbedBlocksByPublishAccess(c, publishAccess, blocks)` for reader roles (`kernel/model/search.go:38`). The same class of data is filtered there and unfiltered here. **Scope note.** A prior review of `getBlockDOMsWithEmbed` confirmed that the per-id publish gate is correctly applied to the *requested* ids. That observation is accurate and is not in dispute, this report concerns the *embedded* blocks resolved downstream in `resolveEmbedContentInBox`, which are not covered by that gate. ### Proof of Concept Precondition: publish mode enabled (default port 6808); anonymous when `Publish.Auth.Enable` is `false`, otherwise any publish reader account. A published document containing an embed query whose results include at least one block in a non-published or password-protected document. ``` POST http://127.0.0.1:6808/api/block/getBlockDOMWithEmbed {"id":"<id of a published block containing an embed query>"} → 200 The returned DOM contains embed-content attributes carrying the content HTML of blocks in documents the reader has no publish access to. ``` Differential check against the filtered sibling, using the same reader session and the same underlying query: ``` POST http://127.0.0.1:6808/api/search/getEmbedBlock {"stmt":"<the same embed query>"} → 200, results filtered by FilterEmbedBlocksByPublishAccess ``` The filtered endpoint withholds the private blocks; the DOM endpoint returns their content. The plural route behaves identically for each requested id: ``` POST http://127.0.0.1:6808/api/block/getBlockDOMsWithEmbed {"ids":["<published block containing an embed query>"]} ``` ### Impact An anonymous reader in publish mode or any publish `RoleReader` can read the content of blocks in documents that are not published, are marked hidden or forbidden, or are protected by a publish password, by requesting a published block that transcludes them. Because embed queries in aggregation-style published documents commonly match across the whole workspace, the volume of exposed content is bounded only by wh | CVE Database V5 | ||
| Medium | 6.9 | EPSS 0.3% | CVE-2026-72792siyuan · Incorrect Authorization Medium6.9EPSS 0.3%CVE Database V5CVE-2026-72792 **CVE:** This vulnerability corresponds to [CVE-2026-72792](https://nvd.nist.gov/vuln/detail/CVE-2026-72792). ### Summary `/api/tag/getTag` filters its results for reader roles through `FilterTagsByPublishIgnore`, which checks only the *visible* publish tier. Documents that are published but password-protected pass that check, so a reader who has never entered a document's publish password receives every tag label used inside it, together with occurrence counts. The project has already treated this exact tier mismatch as a vulnerability on a sibling path: commit `82e9ded42` ("Enforce publish access for graph nodes") moved the graph endpoint off the visible-only filter and onto a password-aware one. `FilterTagsByPublishIgnore` was not upgraded alongside it. ### Details | Item | Detail | |---|---| | Route | `kernel/api/router.go:194` `POST /api/tag/getTag` → `model.CheckAuth` → `getTag` | | Middleware | `CheckAuth` only: no `CheckReadonly`, no `CheckAdminRole` | | Guard | Present but at the wrong tier: visible-only, no password check | | Exposed | Every tag label (`#label#` text) and its occurrence count inside password-protected but visible documents | **The tier mismatch.** For reader roles, `getTag` filters via: ```go publishIgnore := GetInvisiblePublishAccess(publishAccess) tags = FilterTagsByPublishIgnore(publishIgnore, tags) ``` `FilterTagsByPublishIgnore` counts a label if `CheckPathAccessableByPublishIgnore(span.Box, span.Path, publishIgnore)` holds, then reads `label := util.UnescapeHTML(span.Content)`. `CheckPathAccessableByPublishIgnore` (`kernel/model/publish_access.go:183`) consults the invisible set only. It returns true for any visible document, including one carrying a publish password. The project's complete gate is `checkBlockTreeAccessableByPublishAccess` (`kernel/model/publish_access.go:225`), which ANDs that same visibility test with `password == "" || CheckPublishAuthCookie(...)`. The tag filter implements the first half and omits the second. The disclosed value is user-authored content, not a structural identifier: `span.Content` is the tag text an author wrote inside the document project codenames, personal names, client names, subject matter and the accompanying count reveals how heavily each appears. **Established as a defect by the project's own remediation.** Commit `82e9ded42` replaced the graph endpoint's visible-only `FilterGraphByPublishIgnore` with a filter that additionally resolves the document's publish password and validates `CheckPublishAuthCookie`. The reasoning that motivated that change applies unchanged here: same input shape, same visible-only body, same class of leaked material. `FilterTagsByPublishIgnore` retains the pre-fix pattern. **Verified unfixed.** At `v3.7.4-alpha.1`, `getTag` still calls `FilterTagsByPublishIgnore`, and that function's body still tests only `CheckPathAccessableByPublishIgnore`. No commit on the development branch touches `kernel/api/tag.go` or the tag filter (`git log` and `git log -S` both empty over that range). **Scope note on the remaining visible-only call sites.** Two further consumers of the `*ByPublishIgnore` tier were reviewed and are not claimed as vulnerabilities in this report: `listDocsByPath` (`kernel/model/filetree.go:1160`), which exposes document titles and is plausibly intentional for navigation, and the identifier-only filter, which returns no authored content. They are noted because the visible-only tier is now a repeated source of defects, and an audit of every `*ByPublishIgnore` call site is the durable remedy rather than a third individual patch. ### Proof of Concept Precondition: publish mode enabled (default port 6808); a published document that carries a publish password and contains at least one tag; a reader session that has not authenticated to that document. ``` POST http://127.0.0.1:6808/api/tag/getTag {} → 200 The returned tag tree includes labels sourced from the password-protected document, with counts, despite the session holding no publish auth cookie for it. ``` Differential check: request the document itself through a password-gated endpoint with the same session and observe that access is refused, while its tag labels remain present in the `getTag` response. ### Impact An anonymous reader in publish mode or any publish `RoleReader` enumerates the tag vocabulary of documents they are not authorized to open, along with usage counts. Tags are author-written free text, so this discloses subject matter, names and internal terminology from documents whose contents the publish password was configured to protect. Confidentiality-only. ### Suggested fix Replace `FilterTagsByPublishIgnore` with a password-aware filter mirroring the one introduced in `82e9ded42` for graph nodes: resolve each span's document password via `GetPathPasswordByPublishAccess` and require `CheckPublishAuthCookie` before the label is counted, in addition to the existing visibility test. More durably, audit | CVE Database V5 |
Page 38 of 133