v0.10.1
This release adds masked paths for host directory bind mounts.
fs.bind(...) can now mount a real host directory through native virtio-fs while hiding selected entries from the guest. This is useful when a sandbox should work against a host checkout but should not see host-only state such as .git, or when the guest should create its own dependency tree instead of using the host's node_modules.
const sandbox = await defineSandbox({
rootfs: rootfs.builtIn("alpine:3.23"),
}).boot({
mounts: {
"/workspace": fs.bind({
source: "/Users/alice/project",
access: "ro",
mask: {
paths: ["/.git", "/node_modules"],
},
}),
},
});In a read-only bind mount, masked paths behave as if they are absent. Directory listings do not include them, and direct guest lookups cannot open them.
Writable bind mounts can also mask paths, but they need explicit writable mask storage. If the guest creates a masked path, Sandbox stores the guest-owned replacement under that storage directory using the same mask-relative path. The original host entry remains hidden and unchanged.
const maskStorage = fs.bind({
source: "/tmp/sandbox-mask-storage/project",
access: "rw",
});
const sandbox = await defineSandbox({
rootfs: rootfs.builtIn("alpine:3.23"),
}).boot({
mounts: {
"/workspace": fs.bind({
source: "/Users/alice/project",
access: "rw",
mask: {
paths: ["/node_modules"],
storage: maskStorage,
},
}),
},
});The mask is enforced in the native virtio-fs layer, below the JavaScript API boundary, so it applies consistently to guest filesystem operations such as lookup, directory listing, open, create, rename, and unlink. The implementation also handles case-insensitive host filesystems so a mask for /.git cannot be bypassed by asking for /.GIT.
Sandbox now rejects unsafe mask storage configurations that would route guest-created masked entries back into the original bind source, including storage aliases, symlink re-entry, and hard-linked files. That keeps masked writable paths isolated from the lower host directory.