SFTP over `msb ssh serve` creates files as root:root regardless of the authenticated guest user, blocking non-root external SSH clients
Love MSB so far, i was trying to connect Claude Desktop to it, however that fails. I am not sure if this is the right way to submit a bug (or that it is a bug at all and I missed something obvious), so let me know if you want this differently.
Description
Files created through the SFTP subsystem of msb ssh serve are always owned by
root:root with mode 0644, no matter which guest user the SSH session
authenticated as. The shell side of the same connection does follow the user.
A non-root user can not handle this from inside the session: the
uploaded file cannot be chmoded or written, and images that ship without
sudo have no way to fix it. The practical effect is that any external SSH
client that uploads-then-executes a helper binary (IDE/editor remote backends,
for example) fails against a non-root sandbox, while working fine as root.
One solution would be to run as root inside the container, however given that Claude is running as user that is not an option: this would mean Claude can change its own guardrails in the container.
Related: #741 (bind mounts leaking host uid/gid) — same "guest sees the wrong
identity for host-side writes". #741's fix, the
uid=<N>,gid=<N> mount option, does not extend to SFTP-created files (see "What does not
work" below).
msb execin the same sandbox creates files as the expected guest user.- Only the SFTP path is affected.
- The guest user cannot
chmodorunlinkthe resulting file (though it can unlink it when it owns the parent directory).
Reproduction
Any OCI image with a non-root user. Below uses a node:24-bookworm-slim-based
image whose default user is user01 (uid 1000), with no sudo installed.
msb create --name sftptest ghcr.io/example/image:latest
msb ssh authorize --file ~/.ssh/id_ed25519.pub
msb ssh serve --host 127.0.0.1 --port 8022 sftptest &
echo hello > /tmp/probe.txt
# shell side: correct user
ssh -i ~/.ssh/id_ed25519 -p 8022 [email protected] 'id -un'
# sftp side: upload into the user's own home
echo "put /tmp/probe.txt /home/user01/probe.txt" \
| sftp -i ~/.ssh/id_ed25519 -P 8022 [email protected]
ssh -i ~/.ssh/id_ed25519 -p 8022 [email protected] \
'stat -c "%A %U:%G %n" /home/user01/probe.txt; chmod +x /home/user01/probe.txt'Actual Behavior
user01 # shell honours the user
-rw-r--r-- root:root /home/user01/probe.txt # upload does not
chmod: changing permissions of '/home/user01/probe.txt': Operation not permittedThe same put run as [email protected] also produces root:root, but there the
session can chmod the result, so the failure only manifests for non-root users.
Expected Behavior
user01
-rw-r--r-- user01:user01 /home/user01/probe.txt
# chmod succeedsFiles created over SFTP should be owned by the guest user the SSH session
authenticated as, consistent with msb exec and with the shell side of the same
connection.
What does not work as a workaround
Each of these was tested on msb 0.7.2:
- Connecting as the non-root user —
user01@androot@produce identicalroot:rootfiles. The writer does not consult the session user. msb create --user user01— no effect on SFTP-created files.- Guest-side
~/.ssh/authorized_keys— auth is host-side only (<MSB_HOME>/ssh/authorized_keys), confirmed after a full sandbox restart. Consistent with the docs. - Pre-creating the target as an executable, user-owned file — overwriting
an existing file does preserve ownership and mode, but clients that
rm-then-put(as the one prompting this report does) land back on the create path. - A read-only parent directory — does not constrain the writer, which is privileged.
--mount-dir ...:uid=1000,gid=1000over the upload target — the mount itself maps correctly (the directory shows asuser01:user01in the guest), but files SFTP creates inside it are stillroot:root. So #741's fix does not extend to this path.
Environment
- msb 0.7.2 (Homebrew, local backend)
- Host: macOS 26.6.2, Darwin 25.6.0, arm64 (Apple silicon)
- Guest: Linux 6.12.109 aarch64 (libkrunfw), root disk
managed, ext4 - Client: OpenSSH from macOS; also reproduced by a third-party GUI client (Claude Desktop) that uploads and executes a helper binary over the same connection
Source: superradcompany/microsandbox