Sandbox
mistral.rs can run model-generated Python code and shell commands in persistent subprocesses. To keep those subprocesses from doing damage, the spawned process is hardened with an OS-level sandbox.
This is only supported on macOS and Linux environments.
On by default for the CLI on Linux and macOS. To tune it, use --sandbox / the [sandbox] TOML table (see Configuration). To turn it off, see Disabling. For full setup examples, see enable code execution and enable shell execution.
The sandbox is not the same as permissioning. --agent-permission ask or deny decides whether model-requested agent actions are allowed to start. The sandbox controls what the subprocess can access after it starts. See permissions and approvals for the cross-API approval model.
Threat model
Section titled “Threat model”The sandbox targets model misbehavior: a confused or jailbroken model generating Python or shell commands that could:
- delete or read arbitrary files (
rm -rf ~,~/.ssh/id_rsa,.env) - exfiltrate data over the network
- fork-bomb, allocate 200 GB, fill the disk
- pivot to other binaries via
subprocess - attach to host processes via
ptrace - load kernel modules, manipulate mounts, etc.
It is not a substitute for OS-level isolation against a determined attacker who can choose arbitrary code or commands. For high-assurance deployments (multi-tenant, untrusted prompts, regulated data), also isolate the mistral.rs process itself with a container or VM, a dedicated low-privilege user, and constrained network egress. --tool-dispatch-url is the alternative when execution should leave the mistral.rs host entirely.
Defaults
Section titled “Defaults”The CLI and TOML configuration default to auto: enabled on Linux and macOS, and a no-op with a warning elsewhere. The three modes:
off- no sandbox.auto- apply whichever layers the host supports (Landlock, seccomp, namespaces; see Linux details).on- same asauto, but a missing layer becomes a hard error at code-execution initialization instead of being skipped.
The sandbox profile controls the filesystem and environment allowlist inside that mode:
developer- default when agent, code execution, or shell execution is enabled. It keeps writes limited to the session workdir, but allows reads from common local toolchain roots such as Conda/venv, pyenv, rustup, nvm, Homebrew, Nix, Java, Bun, Deno, and selected compiler/library search paths. Its default network mode isfull.restricted- for tighter deployments. It allows system/runtime reads plus the session workdir and explicitly configured paths. Its default network mode isloopback.
The programmatic surfaces behave differently: CodeExecutionConfig and ShellConfig in the Python and Rust SDKs default to no sandbox. Omitting sandbox_policy (or passing None) is equivalent to --sandbox off; the sandbox engages only when a SandboxPolicy is constructed and attached. An application embedding mistral.rs as a library does not inherit the safer CLI default and is responsible for choosing a policy.
The restricted profile default policy:
| field | default |
|---|---|
max_memory_mb | 2048 |
max_cpu_secs | 600 |
max_procs | 64 (additional tasks for the run UID on Linux; see Linux details) |
max_open_fds | 1024 |
max_file_sz_mb | 256 |
network | loopback |
The developer profile uses the same limits and defaults to network = "full" unless network is explicitly set. When rlimits apply and a configured tool timeout exceeds max_cpu_secs, code and shell execution raise max_cpu_secs to match and log a warning.
On macOS, the resource cap fields are accepted for configuration compatibility but are not enforced by Seatbelt. Filesystem and network isolation still apply.
Choosing a profile
Section titled “Choosing a profile”The examples below are TOML configuration snippets for mistralrs from-config -f <path>. See the full TOML configuration reference for where these sections fit in a complete config file.
For local agent use, start with developer:
[runtime]agent = true
[sandbox]mode = "auto"profile = "developer"This is the default when agent = true, enable_code_execution = true, or enable_shell = true, so the explicit profile line is mainly documentation for future readers of the config.
Use restricted when you want tighter filesystem and network defaults:
[sandbox]mode = "auto"profile = "restricted"network = "loopback"Use mode = "on" when startup should fail if requested sandbox layers are unavailable:
[sandbox]mode = "on"profile = "restricted"network = "none"Use mode = "off" only when you intentionally want subprocesses to run with full host access:
[sandbox]mode = "off"The profile does not change the basic write rule: generated code and shell commands can write the session workdir and explicitly configured write paths, not arbitrary home directories.
| Profile | Best for | Reads | Writes | Default network |
|---|---|---|---|---|
developer | Local agents, Skills, package managers, language runtimes, and project analysis tools. | System/runtime paths, discovered toolchain roots, PATH entries, configured read paths, and the session workdir. | Session workdir and configured write paths. | full |
restricted | Production-style deployments and prompts from users you do not fully trust. | System/runtime paths, configured read paths, and the session workdir. | Session workdir and configured write paths. | loopback |
Configuration
Section titled “Configuration”CLI flags (--sandbox, --sandbox-profile, --sb-max-memory-mb, --sb-max-cpu-secs, --sb-max-procs, --sandbox-network) and the [sandbox] TOML table expose the common controls: mode, profile, memory, CPU, process count, and network. The programmatic SandboxPolicy also exposes open-file and written-file-size caps. Schemas: TOML configuration, generated CLI reference. Worked mistralrs serve examples are in enable code execution and enable shell execution.
The MISTRALRS_SANDBOX={auto|on|off} env var overrides only the mode. It has lower precedence than an explicit CLI/TOML mode and higher precedence than the default auto. It does not choose the profile or network policy.
A working directory chosen with --code-exec-workdir or --shell-workdir is made writable inside the sandbox and shared across sessions: anything written there persists and is visible to subsequent sessions.
Linux details
Section titled “Linux details”Applied in order:
-
Env scrub. All inherited env vars are dropped; only a small allowlist (
PATH,LANG,LC_ALL,LC_CTYPE,TERM,HOME,TMPDIR,PYTHONHASHSEED,PYTHONIOENCODING,PYTHONUNBUFFERED) is replayed. The developer profile also replays non-secret toolchain location variables such asCONDA_PREFIX,VIRTUAL_ENV,PYENV_ROOT,NVM_DIR,RUSTUP_HOME, and compiler/library search paths. Secrets such asHF_TOKEN,HF_HOME,HF_HUB_CACHE,AWS_*, andOPENAI_API_KEYare not included by default.HOMEand the XDG cache/config/data dirs are re-pointed at the session workdir. -
Process-count rlimit.
RLIMIT_NPROCis applied before namespace setup. Linux counts it per real UID, somax_procsis applied as additional task headroom above the current UID task count, then clamped to the inherited hard limit. -
Namespaces (when unprivileged user namespaces are available).
unshare(CLONE_NEWUSER|CLONE_NEWIPC|CLONE_NEWUTS)plusCLONE_NEWNETwhennetwork = "loopback"and network namespaces are available. UID 0 inside the ns is mapped to the caller’s UID outside. PID namespace isolation is not applied:unshare(CLONE_NEWPID)only affects future children of the calling thread, and we’re already past the fork that became the tool subprocess. Real PID isolation would require a launcher binary. -
Bring up loopback. If
network = "loopback"uses a network namespace,ioctl(SIOCSIFFLAGS)brings uploinside the new netns. Ifnetwork = "none", no network namespace is required because seccomp deniessocket(2). -
Landlock (kernel 5.13+). Read access is allowed to a static set of system paths (
/usr,/lib,/lib64,/bin,/sbin,/etc,/opt,/proc/self, selected/sysCPU info, and null/random/zero devices). The developer profile adds read access to discovered toolchain roots. The per-session workdir gets read+write access. Anything else returnsEACCES. -
rlimits.
RLIMIT_AS,RLIMIT_CPU,RLIMIT_NOFILE,RLIMIT_FSIZEper policy, clamped to the inherited hard limit.RLIMIT_CORE = 0. -
seccomp-bpf deny-list (when filter install is available). Returns
EPERMfor:ptrace,mount,umount2,pivot_root,chroot,unshare,setns,keyctl,add_key,request_key,bpf,perf_event_open,kexec_load,init_module,finit_module,delete_module,reboot,swapon,swapoff,clock_settime,settimeofday,setdomainname,sethostname,acct,quotactl,io_uring_setup, plusioperm,iopl,nfsservctlon x86_64.When
network = none,socketis also denied. Whennetwork = loopback,AF_NETLINKandAF_PACKETsockets are denied (everything else stays allowed inside the netns).
Best-effort additions:
- cgroup v2. When
/sys/fs/cgroup/cgroup.controllersis delegated, a fresh scope is created withmemory.maxandpids.maxset per policy, and the child PID is moved into it. Silently skipped otherwise.
Fallback when namespaces or seccomp are unavailable:
- No unprivileged user or network namespaces: the remaining available layers still apply, minus the missing namespace layer.
network = "loopback"without a network namespace: there is no network isolation; usenetwork = "none"to denysocket(2)without network namespaces.- No seccomp:
network = "none"cannot be enforced by the sandbox. - Want a hard failure instead of silent fallback: set
mode = "on"instead of the default"auto", which turns missing filesystem or requested network isolation into a hard error at code-execution initialization.
HF_TOKEN, HF_HOME, and HF_HUB_CACHE are deliberately excluded from the default env allowlist: model-generated code can print env vars before any network restriction kicks in. To pass other tokens or secrets through, list them in extra_env.
macOS details
Section titled “macOS details”Argv is wrapped with sandbox-exec -p <profile>. The generated SBPL profile denies by default, allows runtime reads from system paths, dyld and timezone databases, Homebrew/MacPorts prefixes, standard device files, and configured read paths. The developer profile adds read access to discovered toolchain roots. The session workdir and configured write paths get read/write access.
The profile also allows native startup operations that Python and shell commands commonly need, including Mach, IOKit, sysctl, file metadata, file ioctl, and executable file maps. These allowances are for process startup and library loading; writes remain limited to the workdir and configured write paths.
Network follows the configured policy: none emits no network rules, loopback allows localhost endpoints, and full allows network*.
Resource rlimits are not applied on macOS. Applying them from the server requires a pre_exec hook, which forces a fork path from an already-running multithreaded process before the subprocess starts. mistral.rs keeps the Seatbelt sandbox for filesystem and network isolation; use a container or VM when macOS deployments need hard memory, CPU, or process-count caps.
Disabling
Section titled “Disabling”Set mode = "off" in the TOML, --sandbox off on the CLI, or MISTRALRS_SANDBOX=off in the env.
A startup warning is logged. With all sandbox layers off, model-generated code and commands have full filesystem, network, and subprocess access as the mistralrs user.
Programmatic use
Section titled “Programmatic use”For end-to-end setup and the Rust/Python SandboxPolicy snippets, see enable code execution and enable shell execution. Python types are documented in the Python API reference. Remember the default: programmatic use is unsandboxed until a SandboxPolicy is attached.