docs/security/hardening.mdx
The defaults are tuned for the common case: running untrusted code that needs the internet. When your threat model is sharper, such as multi-tenant, credential-handling, or fully offline, tighten the knobs below. Each one is independent, so apply the ones that fit.
If a workload doesn't need the network, remove it. Nothing to filter is the strongest filter.
<CodeGroup> ```bash CLI msb create python --name isolated --no-net ```let sb = Sandbox::builder("isolated")
.image("python")
.network(|n| n.enabled(false))
.create()
.await?;
await using sb = await Sandbox.builder("isolated")
.image("python")
.disableNetwork()
.create();
from microsandbox import Network, Sandbox
sb = await Sandbox.create("isolated", image="python", network=Network.none())
When a workload needs only a handful of destinations, switch from allow-public to deny-by-default and allow exactly what's required. In any allow-by-default policy, remember to deny@meta so the cloud metadata service stays blocked.
msb create alpine --name restricted-worker \
--net-default-egress deny \
--net-rule "allow@public:tcp:443,allow@host:udp:53"
See Networking overview for the full rule syntax and SDK equivalents.
Two independent steps, both worth taking for untrusted code:
no_new_privs, drops the mount-admin capability, and forces nosuid,nodev on user mounts.msb create python --name worker --user app --security restricted
The restricted profile is incompatible with workloads that need those capabilities, such as sudo or Docker-in-Docker. See Isolation boundary for the SDK forms.
openat2 containment is strongest.trust_host_cas off unless you're behind a corporate MITM proxy.| Use case | Network | In-guest privilege | Storage |
|---|---|---|---|
| Trusted internal tool | Default public egress | Root is fine | Mounts as needed |
| Untrusted code / AI agent with internet | Default, or deny-by-default allowlist | Non-root + restricted | Read-only mounts |
| Multi-tenant / per-user | Deny-by-default allowlist | Non-root + restricted | No shared writable volumes, one sandbox per tenant |
| Credential-handling egress | Deny-by-default + TLS interception | Non-root + restricted | Minimal and read-only, with narrow secret allow lists |
| Fully offline / compute-only | --no-net | Non-root + restricted | Read-only or none |
These knobs shrink the blast radius and tighten what a workload can reach. The boundary they sit on top of is still the hypervisor. See the security model overview for what that boundary does and doesn't cover.