{"uuid": "9092a0fe-1331-49a7-a93a-8da6e7338549", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-85622", "type": "seen", "source": "https://gist.github.com/mtholmquist/ab550712a4628c7c7c4705bceccd93b3", "content": "# AppFlowy-Cloud: bulk publish endpoint performs no workspace authorization\n\n| | |\n| --- | --- |\n| **Supplier** | AppFlowy (AppFlowy-IO) |\n| **Product** | AppFlowy-Cloud \u2014 https://github.com/AppFlowy-IO/AppFlowy-Cloud |\n| **Weakness** | CWE-862, Missing Authorization |\n| **Affected** | &gt;= 0.7.2, through 0.9.64 and the final commit `351e8bd`. No fixed version. |\n| **Severity** | 7.7 \u2014 `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:N` |\n| **Reported** | 2026-09-02 to `support@appflowy.io`. No response. |\n| **Finder** | Michael Holmquist (`mtholmquist`) |\n\n## Summary\n\nThe bulk publish endpoint in AppFlowy-Cloud does not check that the caller is a member of the workspace it is publishing into. Any authenticated user can publish content into another tenant's public namespace, which is then served to unauthenticated visitors.\n\n## Affected component\n\n`src/api/workspace/publish.rs`. The handler `publish_collabs` never calls `check_workspace_owner_or_publisher`, while its siblings in the same file do:\n\n    publish_collabs      :314, :443    no authorization check\n    unpublish_collabs    :406, :592    checks\n    patch_collabs        :628          checks\n\nThe newer `publish_page_handler` calls `enforce_role_weak`. So the gap is specific to this handler rather than a module-wide absence of authorization.\n\n## Establishing the range\n\n`check_workspace_owner_or_publisher` is absent from the file entirely at 0.6.0. From 0.7.2 onward the helper exists and is called from the three siblings above but never from `publish_collabs`. I fetched `publish.rs` at 0.7.2, 0.8.0, 0.9.0 and 0.9.64 and counted call sites at each; the count is four every time \u2014 the definition plus the three siblings. The final archived commit `351e8bd` is byte-identical to 0.9.64 at this file.\n\nNo introducing commit is asserted. The lower bound is the first tag at which the pattern is observable, not a git-blame result.\n\n## Impact\n\nAn authenticated user who is not a member of the target workspace can write into that workspace's public publish namespace. Published content is served without authentication, so the attacker controls what visitors to another tenant's public pages receive.\n\n## Status\n\n`AppFlowy-Cloud` was archived on 2026-08-30 with this unfixed. Per its README, AppFlowy moved to an open-core model and the maintained server is now a closed-source commercial fork, so no fix can land in this repository and self-hosters running the open-source server have no upgrade path for it.\n\nThe archived repository is read-only and accepts no new issues, which is why this record is published here.\n\n## Disclosure\n\nReported privately to `support@appflowy.io` on 2026-09-02. No acknowledgement. That address has received six reports since 2026-08-10 and has answered none of them. AppFlowy-Cloud has no GitHub private vulnerability reporting \u2014 the API returns HTTP 422, \"Repository must be public and not archived\" \u2014 and the organisation publishes no `SECURITY.md` or `security.txt`.\n\nThis record is published to serve as a public reference for CVE assignment. Exploitation steps and proof-of-concept material are deliberately omitted: the defect is unfixed and no patched version exists.\n\n## Not a duplicate\n\nThis is distinct from `CVE-2026-85619` and `CVE-2026-85622` (reported by George Chen, issues #1624 and #1629). Those concern a collab access-control check that runs but ignores its object id, in `libs/access-control`. This handler never consults collab access control at all, needs only a victim `workspace_id` rather than an `object_id`, and writes to the public publish namespace. Applying the fix for either of those CVEs in full leaves this open.\n", "creation_timestamp": "2026-09-09T17:22:57.333031Z"}