teableio/teable: Cross-base folder rename through incorrect object authorization in PATCH /api/base/:baseId/node/folder/:folderId
What fixes it
No source in this snapshot names a fixed version.
Description
Summary
An authenticated user with base|update permission on Base A can rename a folder in Base B, despite having no membership or ordinary private access to Base B. The route authorizes the URL’s baseId, but the final database update selects the folder using folderId alone. This was reproduced on a locally hosted Teable instance at commit 5ef2238883cad7c3980084de9a9031135fb9734f.
Details
The folder PATCH controller requires base|update. PermissionGuard selects the URL baseId as the resource to authorize. However, BaseNodeFolderService.renameFolder ultimately calls baseNodeFolder.update with where: { id: folderId }, without requiring the folder to belong to the authorized Base. The sibling folder DELETE operation uses { baseId, id: folderId }. The required victim identifier is BaseNodeFolder.id (bnf…), not the folder node’s BaseNode.id (bno…). In the tested scenario, a legitimate password-free, read-only folder share exposed the bnf… value as the visible node’s resourceId. The share provided an identifier; it was not used to authorize the private PATCH.
Proof of concept
All requests below were made against an authorized localhost instance using disposable accounts and resources. No hosted Teable deployment was contacted.
- Account A owned Base A. Account B owned a separate Base B and Folder B. A was absent from B’s Base and Space collaborator lists. A’s guarded reads of Base B, Space B, and Base B’s node list returned 403 without a share header.
- B created a folder-node share with allowEdit:false and no password. An anonymous share-scoped node-list response exposed Folder B’s node id=bno1Ywb0F8Hdhps6XTJ and resourceId=bnfAwNmSGknfH4t4S6V.
- As a positive control, A renamed its own Folder A through the same PATCH route and confirmed the change through an owner read.
- Using A’s ordinary authenticated session, with no share or template header, send:
PATCH /api/base/bsefs5XjyDR7O9PB924/node/folder/bnfAwNmSGknfH4t4S6V
Content-Type: application/json
{"name":"cross-boundary-folder-d780904d3f"}The response was 200 with Folder B’s ID and the supplied name. More importantly, B’s independent owner reads confirmed that Folder B in Base B changed from victim-folder-original-d780904d3f to cross-boundary-folder-d780904d3f. B then restored the original name.
- In a separate run, B created a fresh read-only share exposing the same folder ID, then deleted it. Anonymous share metadata returned 404, and node-list access with the deleted share header returned 403. A nevertheless used its ordinary private session and the retained folder ID for one cross-base PATCH. B’s owner read confirmed the new name; B restored the folder afterward.
Impact
The confirmed impact is a persistent, unauthorized rename of a folder in another user’s Base. An attacker needs an authenticated account with update permission on an unrelated Base and the exact victim bnf… folder ID. A legitimate read-only share supplied that ID in the tested path, and revoking the share did not prevent the private rename once the ID was known.
This report does not claim record modification, deletion, privilege escalation, private-content disclosure, or discovery of arbitrary unknown folder IDs.
Reported by Team TokenManiZo (https://github.com/TokenManiZo) WHS-4th.
Text from GitHub Advisory Database
Affected versions 1
- teableio/teable, other< release.2026-10-12T12-45-53Z.3331GitHub