fix(preview): refuse ~/ in a Docker case; document the folder-route gate

A Docker case is a local session for the file routes, but `~` inside the
container is the container's own seeded home. Expanding `~/x.png` on the host
opened a different file than the one the agent printed. The attachment POST
and POST …/folders now answer 400 for `~/` when the session has `docker` set
(absolute paths are unaffected: the workspace is a bind mount).

Docs: the resolved-target gate, the route-parameter limit, the listing join
rule and the Docker `~/` refusal in architecture-invariants.md,
security-architecture.md and CLAUDE.md.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
RandalixandClaude Sonnet 5.5 committed 2026-10-12 12:07:39 +02:00
1 parent 6bfc1b88d8
commit 3c08971ff8
5 files changed
+68 -5

No files matched your search

+3
View File
@@ -382,6 +382,9 @@ left out). The grant is an id for a resolved folder; files are served by
`folderId` + a bare file name only (no `/`, `..` or NUL, supported type), and each
request re‑runs `resolveServableAttachmentPath` on the joined path, so a file that
was swapped for a symlink to a blocked target after listing is still refused.
The file a symlink resolves to is held to the attachment gate as well (supported
extension, regular file), so a supported-looking name cannot serve an arbitrary
file, and a FIFO or device node is never opened.
In multi‑user mode a regular user is held to the filesystem path picker's rule
(`folderAllowedForUser`): the folder, and again each served file after symlink
resolution, must sit inside their own `userSpacePath` or the session's