---
title: "Process-Level Sandboxing"
---
import RepoFile from '../../../../components/RepoFile.astro'


**Status**: Proposed — research captured, no implementation committed

## Problem

Jackin's current isolation model operates at two coarse granularities:

- **Git-level isolation** (shipped): `shared | worktree | clone` modes control how each mount is materialized per agent session. This governs filesystem branching, not command-level access control.
- **Runtime-level isolation** (deferred): `dind | microvm` modes determine which compute boundary the entire workspace runs inside. This governs the VM or container boundary, not individual operations inside it.

Neither layer addresses the gap in between: **individual tool calls made by an agent during a session have unrestricted access to everything inside their sandbox boundary.**

When an agent runs `npm install` to set up a project, that process can read `~/.ssh/id_rsa`, write to `/etc`, reach arbitrary network endpoints, and inherit every secret injected at container launch. When an agent generates and runs a shell snippet it composed itself, that snippet runs with the same trust level as the entrypoint. There is no per-operation access control — the entire container or VM is the trust boundary, and once the agent is inside it, every subprocess inherits the same permissions.

This is the gap process-level sandboxing fills. It sits *below* the container/VM boundary, wrapping individual commands in OS-native isolation so that each operation gets only the access it needs.

## The Isolation Tier Stack

A complete isolation strategy for AI-agent workspaces has at least three tiers:

```
Tier                     Boundary granularity         Overhead
─────────────────────────────────────────────────────────────────
Process sandbox          Per operation                < 10 ms
Container / DinD         Per workspace session        100–500 ms
MicroVM                  Per workspace session        1–5 s
```

The [selectable sandbox backends](/reference/roadmap/selectable-sandbox-backends/) roadmap item covers the container-to-microVM step. This item covers the process sandbox tier — the innermost ring that wraps individual shell commands, build steps, and AI-generated code invocations.

The two tiers are complementary, not competing. A microVM boundary prevents a container escape from reaching the host. A process sandbox prevents a single bad command from reading every secret inside the VM.

## Zerobox: The Reference Implementation

[Zerobox](https://github.com/afshinm/zerobox) is a lightweight, cross-platform process sandboxing tool written in Rust. It originates from OpenAI's production Codex sandbox runtime and is now open source.

### What it does

Zerobox executes a command with deny-by-default access controls:

- **Filesystem**: reads and writes are blocked unless explicitly permitted via `--allow-read`, `--allow-write`, `--deny-read`, `--deny-write` path flags.
- **Network**: all outbound connections are blocked unless the target domain is listed via `--allow-net`. Restricted to named domains, not IP ranges.
- **Environment**: only a minimal set of variables (`PATH`, `HOME`, `TMPDIR`) pass through by default. Secrets injected at container launch are invisible to sandboxed subprocesses.
- **Credential injection**: a built-in network proxy intercepts outbound HTTPS connections and substitutes real API keys *at the proxy layer*, so the sandboxed process never sees the real credential values. The process sends requests using placeholder values; the proxy rewrites them to the real tokens only for approved host names. This is the same architecture Docker Sandboxes uses for credential isolation.

The overhead is roughly 10 ms per invocation and about 7 MB of memory. There is no daemon, no separate container layer, no image build step.

### Platform implementation

| Platform | Mechanism |
|---|---|
| Linux | Bubblewrap (unprivileged user namespaces), Seccomp (syscall filtering), Landlock (kernel 5.13+, filesystem restrictions via LSM) |
| macOS | Apple Seatbelt (`sandbox-exec`, available since macOS 10.5) |
| Windows | Planned (restricted tokens + ACLs + firewall rules) |

On Linux, the combination of Bubblewrap + Seccomp + Landlock creates defense-in-depth without requiring root or a privileged sidecar. On macOS, Seatbelt runs kernel-enforced policy without any extra dependencies. Neither path uses a container engine — process sandboxing and container isolation compose independently.

### Snapshot and restore

Zerobox includes a snapshot module (Blake3 + Merkle trees + LZ4 compression) that can capture filesystem state before a command runs and restore it afterward. This is relevant to the [session snapshot and rollback](/reference/roadmap/session-snapshot-rollback/) roadmap item: a lightweight, per-operation snapshot is faster and cheaper than a full container or VM checkpoint and is sufficient for many "undo the last build step" use cases.

### Maturity

Zerobox is in early active development (v0.2.x as of May 2026, roughly 580 GitHub stars, daily release cadence). It is not yet production-stable. APIs may change. The Rust SDK (`zerobox` crate), TypeScript SDK (npm `zerobox`), and Python SDK (PyPI `zerobox`) are all available.

Given the pre-1.0 state, the right posture for Jackin is to track zerobox and treat it as a reference implementation that defines the architecture — not to depend on it as a pinned production dependency today.

## Codex CLI Sandbox Mode

OpenAI's [Codex CLI](https://github.com/openai/codex) runs each shell command it issues through a process sandbox in its default `suggest` mode and in `full-auto` mode. The underlying runtime is zerobox: when Codex CLI tells the user it is running a command in "sandbox mode", it is invoking zerobox with a policy derived from the workspace's declared network allow-list and the set of paths Codex is currently working in.

This is the production pattern worth understanding for Jackin:

- The *agent entrypoint* (Claude Code, Codex, Amp) runs with normal container permissions.
- Each *tool call* (shell command, file write, subprocess) is wrapped in a process sandbox scoped to the minimal access that operation requires.
- The agent's session continues uninterrupted; only the individual subprocess is sandboxed.

The result is that an agent can run thousands of sandboxed tool calls per session with negligible overhead, while a single miscoded command cannot read a secret or exfiltrate data to an untrusted host.

## Why This Matters Before MicroVM

The [selectable sandbox backends](/reference/roadmap/selectable-sandbox-backends/) item is deferred — it requires a dedicated design pass, a backend abstraction layer, and per-provider integration work. Process-level sandboxing can be adopted today, inside the existing DinD container, without waiting for the microVM track to land.

The two improvements address different attack surfaces:

| Scenario | Container boundary helps? | Process sandbox helps? |
|---|---|---|
| Agent escapes container to host | Yes (microVM closes this further) | No |
| Agent's tool call reads a secret it shouldn't | No | Yes |
| Agent's tool call writes to an unrelated path | No | Yes |
| Agent's tool call phones home to a malicious endpoint | Partially (no per-operation policy) | Yes (per-operation network allowlist) |
| Agent's build step corrupts workspace state | No | Yes (snapshot + rollback) |

Process sandboxing is the layer that controls *what individual operations can do inside the sandbox*, complementing the layer that controls *what the sandbox can see of the host*.

## Integration Shape for Jackin

This section captures early thinking on how process-level sandboxing could surface in Jackin. It is not a committed design.

### Entrypoint wrapping

The construct image and runtime entrypoint could install a sandboxing shim and configure the agent runtime to route shell executions through it. For Claude Code, this aligns with its `--dangerously-skip-permissions` full-auto model: the agent still runs without interactive permission prompts, but each shell command it issues is constrained by a Jackin-managed sandbox policy rather than running unrestricted.

### Policy derivation

Jackin already knows, per workspace mount, which host paths are shared and with what intent. A natural extension is to derive a per-mount process-sandbox policy from the same mount configuration:

```toml
[[mounts]]
path = "~/Projects/my-service"
# read-write access → allow-write for this path
# nothing else → deny writes elsewhere

[[mounts]]
path = "~/Projects/shared-libs"
readonly = true
# read-only access → allow-read for this path, deny-write
```

The sandbox policy for any command running against these mounts would be derived automatically: allow writes to `~/Projects/my-service`, allow reads from `~/Projects/shared-libs`, deny everything else.

### Credential proxy

Zerobox's built-in network proxy implements the same credential injection architecture that Docker Sandboxes uses: secrets never enter the sandboxed process; the proxy substitutes them only for approved host names. This is a direct implementation path for the credential proxy item in the security roadmap. Rather than building a standalone proxy, Jackin could delegate this to the process sandbox layer for commands that run inside the agent session.

### Sandboxed DinD commands

Some agents (role repos that invoke Docker to build sibling containers) issue Docker CLI commands as part of their workflow. These could be sandboxed separately from the agent entrypoint: the agent runs with normal permissions, but its `docker build` or `docker run` invocations are wrapped with a policy that restricts which paths the build context can include and which registries the pull can reach.

## Relationship to Other Roadmap Items

| Roadmap item | Relationship |
|---|---|
| [Selectable sandbox backends](/reference/roadmap/selectable-sandbox-backends/) | Process sandbox is the innermost tier; microVM is the outermost. Both are needed for the strongest isolation model. This item fills the per-operation gap that VM boundaries cannot close. |
| [Network egress policy](/reference/roadmap/network-egress-policy/) | Zerobox implements per-process network policy enforcement at the OS level. Its allow-list mechanism is a concrete implementation path for egress policy inside agent sessions. |
| Credential proxy (planned) | Zerobox's built-in HTTPS proxy with per-host credential injection is a direct implementation of the credential proxy architecture described in the roadmap overview. |
| [Session snapshot and rollback](/reference/roadmap/session-snapshot-rollback/) | Zerobox's snapshot module (Blake3 + Merkle + LZ4) provides per-operation filesystem checkpointing as a lightweight alternative to full container/VM checkpoints. |
| [Rootless DinD](/reference/roadmap/rootless-dind/) | Both are hardening steps that improve the DinD security posture without requiring microVM. Rootless DinD reduces the sidecar's host privilege; process sandboxing reduces per-operation access inside the container. |

## Alternatives

### gVisor

gVisor interposes at the syscall layer rather than the filesystem and network layer, providing a user-space kernel that intercepts every system call a process makes. It offers strong process isolation but adds meaningful latency per syscall and does not provide per-process network policy without additional infrastructure. It is more relevant as a container runtime hardening layer than as a per-operation sandboxing mechanism.

### WebAssembly + WASI

WASI (WebAssembly System Interface) provides capability-based isolation for portable Wasm modules. The isolation model is strong and the overhead is low, but it requires code to be compiled to WebAssembly — not applicable to arbitrary shell commands or native build toolchains.

### Custom seccomp profiles

The DinD container already applies a default seccomp profile. Jackin could tighten this by supplying a custom profile tuned to what agent workloads actually need. This is a weaker and more brittle mechanism than process sandboxing: it restricts syscalls globally for the whole container rather than per-operation, and maintaining correct seccomp profiles for diverse agent toolchains is operationally expensive.

## Open Questions

1. **Which zerobox integration surface?** Shell-out to the `zerobox` CLI, embed the Rust crate directly, or wait for a more mature API surface before committing to either.
2. **Policy authoring burden.** Who specifies which paths and hosts each agent operation may access? Should Jackin derive this from mount configuration automatically, expose it in `jackin.role.toml`, or leave it to a default-open policy with operator override?
3. **Interaction with Bubblewrap inside the DinD container.** DinD currently runs a privileged container. Bubblewrap requires unprivileged user namespaces, which may be restricted by AppArmor on some hosts. Compatibility testing is needed before committing to the Linux mechanism.
4. **Performance at scale.** Zerobox reports 10 ms overhead per invocation. An agent making 500 tool calls in a session adds 5 seconds of overhead. At 1000 calls, 10 seconds. Whether this is acceptable depends on the operation mix.
5. **Snapshot policy.** Should snapshots be taken before every command, only before commands classified as risky, or only on explicit operator opt-in?

## Related Files

- <RepoFile path="docker/runtime/entrypoint.sh" /> — current runtime entrypoint; wrapping point for a sandboxed execution shim
- <RepoFile path="docker/construct/Dockerfile" /> — construct image; install point for the zerobox binary
- <RepoFile path="src/runtime/launch.rs" /> — launch orchestration; policy derivation hook
- <RepoFile path="src/workspace/mounts.rs" /> — mount resolution; source of per-mount access intent
- [Selectable sandbox backends](/reference/roadmap/selectable-sandbox-backends/) — the VM/container isolation tier this item complements
- [Network egress policy](/reference/roadmap/network-egress-policy/) — the per-workspace network policy item; process sandboxing operates at finer per-operation granularity
- [Security model](/guides/security-model/) — current operator-facing security boundary statement
