Sandboxing — Concepts
Sandboxing exists so an agent can run code you don’t fully trust — without that code harming your machine, reading your secrets, or leaving you in a broken state. This page explains the model. For step-by-step configuration, see Run Code in Sandbox.
What sandboxing is for
Section titled “What sandboxing is for”Every setting on the Sandbox page serves one of five goals:
- Run untrusted / agent-generated code — the agent writes and runs a script you didn’t review line by line. The worst case is a discarded container, not a wiped home directory.
- Process untrusted external inputs — a downloaded CSV, a scraped page, a user-supplied file. A malicious payload can’t escape the container.
- Reproducible per-language environments — “run in Python 3.12 / Node 20” gives the same result on any host, independent of what’s installed locally.
- Resource-capped, timeboxed execution — a runaway loop or fork bomb is killed by hard CPU/memory/time limits (kernel cgroups), not left to melt the host.
- Network control — turn outbound network off entirely (Strict), so downloaded or generated code can’t call home.
The UI is organised around that intent — three profiles — not around fifteen individual fields.
Two systems (kept separate by design)
Section titled “Two systems (kept separate by design)”Snippbot has two distinct isolation mechanisms. They are not merged; the profile you pick composes them.
| OS-level fence | Container engine | |
|---|---|---|
| What | A permission cage around a process running on the host | The command runs inside a container with its own filesystem, namespaces, and cgroups |
| How | macOS Seatbelt (sandbox-exec) / Linux bwrap / firejail | Docker / Podman / a process fallback |
| Strength | Weaker boundary; shares the host kernel & toolchain | Strong isolation, reproducible, disposable |
| Cost | ~0 ms, no runtime needed | A running runtime + ~200 ms cold start |
| Governs | The agent’s own commands — loop checks, MCP servers | Untrusted code Snippbot runs — run_code, workflow tool steps (installed tools: follow-up) |
The Sandbox settings page configures the container engine. The OS fence is configured separately (it governs loops and MCP), and the page’s “Where commands run” panel always tells you which system applies to each context.
Isolation Profiles: Off / Safe / Strict
Section titled “Isolation Profiles: Off / Safe / Strict”Pick a profile; it sets the underlying fields for you. Advanced settings can fine-tune any profile (which then shows as Custom).
| Profile | Behaviour | Use when |
|---|---|---|
| Off | All commands run on the host. | Fully trusted local dev. |
| Safe (default) | Host by default; risky commands auto-containerize based on a risk score. Arbitrary code (run_code) is always containerized. | Everyday agent work. |
| Strict | Every command Snippbot runs — run_code, bash from API-model and claude-native agents (with the default contain gate), workflow tool steps — is containerized, with no network. | Untrusted code, shared or production machines. |
The profile is derived, not stored: it’s read back by comparing four fields
— mode, scope, workspace_access, and whether the network is enabled — to
the profile bundles. Change any of those four and you get Custom; tuning
resources, GPU, or mounts keeps the profile label.
How “Safe” decides
Section titled “How “Safe” decides”In Safe mode each shell command is scored 0–1 by an operation detector (does it delete files, modify the system, reach the network, run recursively?). Commands scoring at or above the risk threshold (default 0.5) run in a container; everything else runs on the host. Two guarantees:
- Arbitrary code is always contained. A regex can’t reliably judge a Python
or JavaScript snippet, so
run_codeis containerized in both Safe and Strict. - Fail-safe. If the scorer is unavailable, the command is treated as high-risk and containerized — Safe never silently drops to the host because of a scoring error.
The file model: how code touches your files
Section titled “The file model: how code touches your files”This is the most misunderstood area.
- Bind mounts, not copies. Your workspace is exposed to the container as a
bind mount at
/workspace. It’s one set of files on disk; a write to/workspace/xis a write to the host path — no sync step. workspace_accessis the mount choice:none— the project is not mounted (clean room).ro— bind-mounted read-only (“analyze my code/data”).rw— bind-mounted read-write (“edit my project / emit files”).
- System files are never mounted. The container sees the image’s OS plus
only what’s bind-mounted — your project, any custom mounts, and a tmpfs.
~/.ssh, other projects,/etc, cloud credentials are simply absent from the container’s namespace.
Where the agent writes, and how files come back
Section titled “Where the agent writes, and how files come back”When the workspace is read-only or unmounted, the agent still needs somewhere to
write. Its working directory is a writable scratch tmpfs (/work), separate
from the read-only project at /workspace. Files the agent creates there are
copied back to the conversation’s files and render inline in chat — your
project is never modified unless you choose rw.
Detection avoids a full-workspace diff: the execute path drops a marker before
the command and copies out files newer than it (or explicit declared outputs),
returning their host paths on the result’s artifacts.
Which “workspace” gets mounted
Section titled “Which “workspace” gets mounted”- A linked project → the project directory.
- Chat with no project → a per-conversation scratch directory (the same store chat uses for agent files) — never your home directory.
workspace_access = none→ nothing is mounted.
Where commands run (execution-context matrix)
Section titled “Where commands run (execution-context matrix)”The container profile governs the paths Snippbot’s own tool executor runs. Other contexts have their own rules — the Sandbox page shows this live:
| Context | Governed by | Behaviour |
|---|---|---|
Agent-generated code (run_code) | Container engine | Always containerized in Safe & Strict — the core “untrusted code” case. |
| Agent bash — API-model agents | Container engine | Routed through Snippbot’s executor; honours the profile (Off → host, Safe → risk-based, Strict → container). |
| Agent bash — claude-native agents | Per claude_native_bash_gate | contain (default) → same as API-model bash (container per profile); gate → allowed/denied on the host per profile; off → host (legacy). |
Installed marketplace tools (custom_python) | Container profile | Blocked under any non-Off profile (untrusted code); runs on the host only when sandboxing is Off. Containerized execution is a follow-up. |
| Workflow tool steps | Container engine | Honours the profile (a step may opt out with sandbox_enabled=False). |
| Loop verifiable command | OS fence | A lightweight pass/fail check — separate from the container profile. |
| MCP tool servers | OS fence | Third-party tool processes run under the fence. |
| Project mode | Host (no sandbox) | Intentionally host-only — project work needs to write to your workspace and run at host speed, so the profile does not apply. |
Platform support
Section titled “Platform support”| Capability | macOS | Linux | Windows |
|---|---|---|---|
| Container engine | Docker/Podman Desktop (Linux VM) | native docker/podman | Docker/Podman via WSL2 only |
| OS fence | sandbox-exec | bwrap / firejail | Unsupported (loops/MCP fencing fail closed) |
process fallback | Seatbelt-backed | bwrap/firejail-backed | ”basic” — minimal isolation |
| GPU passthrough | Not supported | NVIDIA + toolkit | via WSL2 |
Runtime status
Section titled “Runtime status”The Sandbox page shows a page-level banner for the current runtime state:
- Live — Docker/Podman is up; commands containerize per the profile.
- Safe/Strict but no runtime — a surfaced degradation: commands run
unsandboxed (or are blocked, if you set fail-closed), and the banner says so.
This is never silent — the engine emits a
sandbox.degradedevent. - Off + no runtime — expected; commands run on the host by design.
See also
Section titled “See also”- Run Code in Sandbox — configuration walkthrough.
- Sandbox API — REST endpoints.