From b3ef2aff738cc4efd974efab9315a6ce6c3de493 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Fri, 14 Aug 2026 21:39:42 +0200 Subject: feat(files): upload into the current directory, and create folders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The per-user quarantine is gone. `.uploads/{user_id}/` was the fix for C5a, and it worked, but it made the shared directory something nobody could organise: every file landed under a uuid nobody recognises. Files now go where the member is looking, most often the root. What the quarantine actually bought is kept, and is now what the tests assert rather than the location: - an existing file is never replaced. That was the real defect — overwriting a file also made the attacker its recorded uploader, and therefore able to delete it through the uploader path - the name allowlist is unchanged - the destination is confined under the shared root That last one is new surface: the directory arrives from the client. safe_subdir() is the single place that decides, with two independent guards — every segment against the name allowlist, and the resolved result under the root — because one of them will eventually be refactored by someone who does not know why it is there. Ten traversal cases are covered, and they fail if both guards go. Also adds `dir_create` (any member may organise a shared directory; audited like anything that writes to the operator's disk) and makes the node report its real directory list in index_sync — folders were inferred from file paths, so a new empty one, or one that had been emptied, simply did not exist as far as the UI was concerned. Two C5a tests changed their assertions deliberately, as C5b's did before: they encoded the quarantine path, which is the thing being removed. The property they existed for is asserted more directly than before. Co-Authored-By: Claude Opus 5 --- packages/meshbay-common/src/meshbay_common/protocol.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'packages/meshbay-common/src') diff --git a/packages/meshbay-common/src/meshbay_common/protocol.py b/packages/meshbay-common/src/meshbay_common/protocol.py index 50e8663..08dc47b 100644 --- a/packages/meshbay-common/src/meshbay_common/protocol.py +++ b/packages/meshbay-common/src/meshbay_common/protocol.py @@ -35,6 +35,8 @@ class MNP: # the wire contract looking as though the endpoint still existed. FILE_UPLOAD = "file_upload" # client pushes file chunk to node FILE_UPLOAD_ACK = "file_upload_ack" # node acknowledges chunk receipt + DIR_CREATE = "dir_create" # client → node: make a directory + DIR_CREATE_ACK = "dir_create_ack" # node → client: created FILE_DELETE = "file_delete" # client requests file deletion FILE_DELETE_ACK = "file_delete_ack" # node confirms deletion STREAM_REQUEST = "stream_req" # client requests MSE video stream -- cgit v1.2.3