docs/changelog/2026-05-29.mdx
Native SSH and SFTP
Sandboxes gain a first-class SSH surface across the CLI and every SDK without running sshd inside the guest. msb ssh <name> opens an interactive session, msb ssh <name> -- <cmd> runs a one-shot command, and msb ssh serve exposes an external SSH transport that standard ssh and sftp clients can connect to after msb ssh authorize registers a key. The SDK SSH namespace in Rust, TypeScript, Python, and Go supports interactive attach, exec, and SFTP, plus an in-process server mode.
msb ssh authorize --file ~/.ssh/id_ed25519.pub
msb ssh serve devbox --host 127.0.0.1 --port 2222
ssh -p 2222 [email protected]
sftp -P 2222 [email protected]
See the SSH overview.
Configurable OCI upper size
The writable upper layer for OCI sandboxes is now configurable, so workloads that generate large amounts of state during a session no longer have to fit inside the previous fixed default. msb run --oci-upper-size 8G ... sets it from the CLI, and sandbox_defaults.oci.upper_size_mib sets the deployment-wide default. The Rust, TypeScript, Python, and Go SDKs gained matching surfaces. Fresh OCI roots default to 4096 MiB; snapshot upper layers are copied as-is.
sandbox = await Sandbox.create(
"worker",
image=Image.oci("python:3.12", upper_size_mib=8192),
)
See the sandbox commands reference.
msb copy and rootfs patch flags
A new msb copy (alias msb cp) moves files host-to-sandbox, sandbox-to-host, within a single sandbox, or across two sandboxes, including recursive directories and symlinks. msb run and msb create accept --copy, --copy-file, --copy-dir, --mkdir, and --rm so a fresh sandbox can be prepared without a separate setup step. Guest paths are validated before the sandbox is created so typos fail fast.
msb run alpine \
--copy ./config.toml:/etc/app/config.toml \
--copy-dir ./certs:/etc/app/certs \
--mkdir /var/cache/app \
--rm /etc/motd
msb copy ./local.txt devbox:/tmp/local.txt
msb copy devbox:/tmp/a otherbox:/tmp/a
See the CLI overview.
Docker-style mount options with enforced ro and noexec
Volume mounts now use the Docker-style source:guest:options shape everywhere and accept ro, rw, nosuid, noexec, and fstype=... (for disk-image volumes). The host-side passthroughfs enforces read-only mounts so the guest cannot remount them writable, and the runtime drops mount-admin capability before user execs so user commands cannot undo ro or noexec. Direct SDK configs are validated before create or start so unsafe guest paths and policy combinations fail early.
msb run --name tools -v ./tools:/tools:ro,noexec alpine -- ls /tools
See the volumes guide.
Env-backed secret shorthand
msb --secret accepts a new ENV@HOST form that reads the value from the same-named host environment variable, so common API keys no longer need to be inlined in command arguments. The existing ENV=VALUE@HOST form is preserved for explicit values and renames. Missing, empty, or non-UTF-8 sources produce a clear error.
msb create python --name agent \
--secret "[email protected]"
See the secrets guide.
Other features
Ip, Cidr, Domain, DomainSuffix, Group, and Any destinations on Rule, alongside the legacy string form. See the Python networking reference.core.clock.sync frame on startup, every 60 seconds, and after the host wall clock jumps by more than 6 seconds. Sandboxes that survive a host sleep or suspend resume with the correct wall time instead of drifting until restart.Host, and observed HTTP/2 :authority, so spoofed or fronted hosts cannot trick the proxy into injecting real secret values. HTTP/2 HEADERS are decoded and re-encoded with bounded HPACK state, and HTTP/1 chunked and fixed-length bodies are rewritten safely.U+FFFD, leak header-only secrets into request bodies, or skip substitution on pipelined follow-up requests.deny rules even when the guest connects to a literal IP with no DNS-cache binding, closing a path that previously let denied domains through over direct-IP HTTPS.65534:65534.SUN_LEN before spawn, with the legacy socket path retained as a fallback.Sandbox.exec(cmd, options_dict) and exec_stream(cmd, options_dict) in the Python SDK now actually apply args and other options, and shell_with(..., timeout=...) honors the same timeout path as exec_with(). create_with_progress() is callable synchronously again.msb ssh commands work without rebuilding from source.