Issue Description
When account A shares a FileNode folder with account B at read level only (mayRead), B can create new nodes anywhere in A’s FileNode tree via JMAP FileNode/set create, including under folders A has not shared with B at all. FileNode/set create does not check that the acting principal holds AddItems (mayAddChildren) on the target parent.
Measured on v0.16.20. crates/jmap/src/file/set.rs is byte-identical in v0.16.27, so the current release should behave the same (not re-measured there).
Expected Behavior
Creating a child node in a shared account requires AddItems (mayAddChildren) on the parent node, mirroring the Modify/Delete checks that update and destroy already perform. Without it, the create is rejected with forbidden.
Actual Behavior
Any recipient of a read-only folder share can create nodes in every folder of the owner’s tree, including folders that were never shared with them.
Reproduction Steps
- Account A creates two top-level folders
XandY. - A shares
Xwith account B granting onlymayRead(shareWith: {<B>: {mayRead: true}}). - As B, call
FileNode/seton A’s accountId with onecreateof an empty folder node (noblobId) whoseparentIdisX. → created, although B only holdsmayReadonX. - As B, repeat with
parentId=Y(never shared with B). → created, although B has no grant onY. - Control: grant B
mayAddChildrenonXand repeat step 3 → created (expected).
Every created node was removed again by A right after the measurement.
Relevant Log Output
None: the requests succeed, so nothing is logged as an error.
Stalwart Version
v0.16.x
Installation Method
Docker
Database Backend
FoundationDB
Blob Storage
S3-compatible
Search Engine
Internal
Directory Backend
Internal
Additional Context
Where in the code (v0.16.20 / v0.16.27)
validate_file_node_hierarchy(crates/jmap/src/file/set.rs:861-870) only rejects top-level nodes (parent_id == 0) in a shared account. For other parents it checks that the parent exists and is a container, not the caller’s rights on it.- The parent handling on create (
set.rs:245-269) copies the parent’s ACL onto the new node and requiresAcl::Shareonly when the request itself setsshareWith. A create withoutshareWithpasses with no per-parent permission check.
Scope check: if B has no FileNode share from A (only a shared calendar or a shared mailbox), FileNode/get and FileNode/set create on A’s account correctly return forbidden (“You do not have access to account …”). So the gap needs at least one FileNode share between the two accounts.
Deployment: Docker image on Kubernetes, two replicas.
Related: the quota side of FileNode/set is already reported in “FileNode ignores disk quota”.
I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.
on
I have searched this support forum (open and closed topics) and confirm this is not a duplicate.
on
I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.
on