Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion content/manuals/ai/sandboxes/security/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ and ICMP are blocked at the network layer.

## Isolation layers

The sandbox security model has four layers. See
The sandbox security model has five layers. See
[Isolation layers](isolation/) for technical details on each.

- **Hypervisor isolation:** separate kernel per sandbox. No shared memory or
Expand All @@ -52,6 +52,9 @@ The sandbox security model has four layers. See
[Deny-by-default policy](defaults/). Non-HTTP protocols blocked entirely.
- **Docker Engine isolation:** each sandbox has its own Docker Engine with no
path to the host daemon.
- **Source-repository isolation (branch mode):** the agent works on a private
in-VM clone with your `.git` mounted read-only. Even an unconstrained
agent cannot corrupt your host repository.
- **Credential isolation:** API keys are injected into HTTP headers by the
host-side proxy. Credential values never enter the VM.

Expand Down
67 changes: 63 additions & 4 deletions content/manuals/ai/sandboxes/security/isolation.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
---
title: Isolation layers
weight: 10
description: How Docker Sandboxes isolate AI agents using hypervisor, network, Docker Engine, and credential boundaries.
keywords: docker sandboxes, isolation, hypervisor, network, credentials
description: How Docker Sandboxes isolate AI agents using hypervisor, network, Docker Engine, source-repository, and credential boundaries.
keywords: docker sandboxes, isolation, hypervisor, network, credentials, git
---

{{< summary-bar feature_name="Docker Sandboxes sbx" >}}

AI coding agents need to execute code, install packages, and run tools on
your behalf. Docker Sandboxes run each agent in its own microVM with four
isolation layers: hypervisor, network, Docker Engine, and credential proxy.
your behalf. Docker Sandboxes run each agent in its own microVM with five
isolation layers: hypervisor, network, Docker Engine, source-repository
(in branch mode), and credential proxy.

## Hypervisor isolation

Expand Down Expand Up @@ -73,6 +74,64 @@
└── [VM] Containers created by agent
```

## Source-repository isolation

When you start a sandbox with `--branch` (see the
[branch-mode workflow](../usage.md#branch-mode)), the agent never works
directly against your host repository. Even with full root inside the VM,
it cannot corrupt your local Git state.

The boundary works like this:

- Your repository's Git root is bind-mounted into the sandbox at
`/run/sandbox/source` as **read-only**. The agent — and anything it
spawns — cannot write to your `.git` directory, your working tree, or
any tracked file via that mount.
- The agent's working copy is a private `git clone --reference` populated
on the sandbox's overlay filesystem. The clone has its own index, its
own refs, and its own working tree. Object storage is shared via
`.git/objects/info/alternates`, so the clone is space-efficient and
full history is walkable, but writes to the clone never reach your
host's object database.
- Your host pulls the agent's commits over a `git-daemon` exposed by the
sandbox on `127.0.0.1:<ephemeral-port>`. The CLI registers it as a
`sandbox-<sandbox-name>` remote on your host repo. Fetching from that

Check warning on line 98 in content/manuals/ai/sandboxes/security/isolation.md

View workflow job for this annotation

GitHub Actions / validate (vale)

[vale] reported by reviewdog 🐶 [Docker.RecommendedWords] Consider using 'repository' instead of 'repo' Raw Output: {"message": "[Docker.RecommendedWords] Consider using 'repository' instead of 'repo'", "location": {"path": "content/manuals/ai/sandboxes/security/isolation.md", "range": {"start": {"line": 98, "column": 48}}}, "severity": "INFO"}

Check failure on line 98 in content/manuals/ai/sandboxes/security/isolation.md

View workflow job for this annotation

GitHub Actions / validate (vale)

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'repo'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'repo'?", "location": {"path": "content/manuals/ai/sandboxes/security/isolation.md", "range": {"start": {"line": 98, "column": 48}}}, "severity": "ERROR"}
remote uses the same trust model as fetching from any third-party
remote: nothing is integrated until you explicitly merge or check out
the fetched refs.

```plaintext
Host repository Sandbox VM
.git/ /run/sandbox/source/ (RO bind mount)
objects/ ◄─────── alternates ───────── clone/.git/objects/
refs/ clone/.git/refs/ (private)
HEAD clone/.git/HEAD (private)
working tree clone/working tree (overlay FS)
remote sandbox-<name> ──── git:// ────► git-daemon :9418
(published 127.0.0.1:<ephemeral>)
```

The practical guarantees:

- **Index and ref corruption are impossible.** Concurrent `git` commands
on the host and inside the sandbox can't race on a shared `.git/index`
or shared refs because there is no shared writable state.
- **No write-back to your working tree.** A compromised or buggy agent
can't drop a `.git/hooks/pre-commit`, modify `.github/workflows/`, or
edit any other tracked file in a way that affects your host until you
fetch and merge from the `sandbox-<name>` remote.
- **No access to your `.git/config`.** Credentials, signing keys, and
global settings declared in your repository configuration stay on the
host. The agent's clone has its own configuration.
- **Cleanup is automatic.** `sbx rm` deletes the clone, the published
port, and the `sandbox-<name>` remote on your host. Nothing leaks
outside the sandbox lifecycle.

In direct mode (no `--branch`), the agent edits your working tree directly
and this isolation does not apply. Use branch mode whenever you want a
strong boundary between the agent's Git activity and your host
repository.

## Credential isolation

Most agents need API keys for their model provider. Rather than passing keys
Expand Down
19 changes: 14 additions & 5 deletions content/manuals/ai/sandboxes/security/workspace.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,16 @@ includes:

## Branch mode

The `--branch` flag lets the agent work on a separate branch. This is a
workflow convenience, not a security boundary: the agent still mounts the full
repository. See the [usage guide](../usage.md) for details.
The `--branch` flag isolates the agent from your host repository: it works
on a private clone inside the sandbox, with your `.git` directory
bind-mounted **read-only** as a reference. This means the agent cannot
modify any tracked file or any byte under `.git/` on your host, no matter
how unconstrained the agent runs. You see the agent's commits only after
explicitly running `git fetch sandbox-<name>`.

See [Source-repository isolation](isolation.md#source-repository-isolation)
for the full boundary, and the [usage guide](../usage.md#branch-mode) for
the workflow.

## Reviewing changes

Expand All @@ -52,10 +59,12 @@ With the default direct mount, changes are in your working tree:
$ git diff
```

If you used `--branch`, the agent's changes are on a separate branch:
If you used `--branch`, the agent's changes are on the `sandbox-<name>`
remote until you fetch and merge them:

```console
$ git diff main..my-feature
$ git fetch sandbox-my-sandbox
$ git diff main..sandbox-my-sandbox/my-feature
```

Pay particular attention to:
Expand Down
127 changes: 62 additions & 65 deletions content/manuals/ai/sandboxes/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,29 @@ time, they may step on each other's changes. See

### Branch mode

Pass `--branch <name>` to give the agent its own
[Git worktree](https://git-scm.com/docs/git-worktree) and branch. This
prevents conflicts when multiple agents, or you and an agent, write to the
same files at the same time. You can set `--branch` on `create`, `run`, or
both.

The CLI creates worktrees under `.sbx/` in your repository root. The
worktree is a separate working directory, so the agent doesn't touch your main
working tree. This means:

- The worktree branches off your latest commit when you create it.
Uncommitted changes in your working tree are not included (`sbx` warns you
if it detects any).
- Files you add or change in your main working tree won't be visible to the
agent, and vice versa. The two directories are independent.
Pass `--branch <name>` to give the agent its own branch and an isolated clone
of your repository inside the sandbox. This prevents conflicts when multiple
agents, or you and an agent, write to the same files at the same time. You
can set `--branch` on `create` or, equivalently, on `run` at create time.

When `--branch` is active:

- The agent works on a private clone living entirely inside the sandbox.
Your repository's `.git` directory is bind-mounted **read-only** as a
reference for the clone's object database, so the agent reuses your local
history without consuming extra disk space.
- The CLI creates the new branch on your host repository and checks it out
if your working tree is clean. If it's dirty, the branch ref is still
created but the checkout is skipped with a warning, so your uncommitted
changes are preserved.
- The sandbox runs a `git-daemon` over a `127.0.0.1`-bound ephemeral port
that exports the in-container clone. The CLI registers it as a Git remote
named `sandbox-<sandbox-name>` on your host repository, so you can pull
the agent's commits with `git fetch`.
- The agent's clone has its own index, refs, and working tree. Concurrent
Git operations on the host and inside the sandbox can't corrupt each
other. See [Source-repository isolation](security/isolation.md#source-repository-isolation)
for the security implications.

#### Starting a branch

Expand All @@ -105,46 +113,44 @@ Use `--branch auto` to let the CLI generate a branch name for you:
$ sbx run claude --branch auto
```

You can also create the sandbox first and add a branch at run time:

```console
$ sbx create --name my-sandbox claude .
$ sbx run --branch my-feature my-sandbox
```

Or set the branch at create time and reuse it on subsequent runs:
You can also create the sandbox first and attach later:

```console
$ sbx create --name my-sandbox --branch my-feature claude .
$ sbx run my-sandbox # resumes in the my-feature worktree
$ sbx run --branch my-feature my-sandbox # same — reuses the existing worktree
$ sbx run my-sandbox # resumes in the my-feature clone
```

#### Multiple branches per sandbox

You can run multiple worktrees in the same sandbox by passing different branch
names:

```console
$ sbx run --branch feature-a my-sandbox
$ sbx run --branch feature-b my-sandbox
```
> [!NOTE]
> A sandbox is bound to the branch chosen at create time. To work on a
> different branch, create a new sandbox with `sbx create --branch
> other-feature ...`. Running `sbx run --branch ...` on an existing sandbox
> with a different branch is rejected.

#### Reviewing and pushing changes

To review the agent's work, find the worktree with `git worktree list`, then
push or open a PR from there:
The CLI wires the agent's in-container clone as a `sandbox-<sandbox-name>`
Git remote on your host repository. Review the agent's work with the same
commands you'd use for any other remote — no `cd` into a worktree, no extra
tooling:

```console
$ git worktree list # find the worktree path
$ cd .sbx/<sandbox-name>-worktrees/my-feature
$ git log # see what the agent did
$ git fetch sandbox-my-sandbox # pull the agent's commits
$ git log sandbox-my-sandbox/my-feature # see what the agent did
$ git diff main..sandbox-my-sandbox/my-feature # full diff
$ git checkout my-feature && git merge --ff-only \
sandbox-my-sandbox/my-feature # fast-forward your local branch
$ git push -u origin my-feature
$ gh pr create
```

Some agents don't commit automatically and leave changes uncommitted in the
worktree. If that happens, commit from the worktree directory before pushing.
Some agents don't commit automatically. If `git log sandbox-<name>/<branch>`
shows nothing new, open a shell in the sandbox and commit from there before
fetching:

```console
$ sbx exec -it my-sandbox bash
$ git -C $(pwd) commit -am "save work"
```

See [Workspace trust](security/workspace.md) for security considerations when
reviewing agent changes.
Expand Down Expand Up @@ -187,31 +193,22 @@ For common signing failures, see

#### Cleanup

`sbx rm` removes the sandbox and all of its worktrees and branches.

#### Ignoring the `.sbx/` directory

Branch mode stores worktrees under `.sbx/` in your repository root. To keep
this directory out of `git status`, add it to your project's `.gitignore`:
`sbx rm` deletes the sandbox, its in-container clone, the published Git
port, and the `sandbox-<sandbox-name>` remote on your host repository. The
local branch the agent worked on stays on your host so you don't lose any
commits you've already fetched.

```console
$ echo '.sbx/' >> .gitignore
```

Or, to ignore it across all repositories, add `.sbx/` to your global gitignore:

```console
$ echo '.sbx/' >> "$(git config --global core.excludesFile)"
```
#### Restrictions

> [!TIP]
> If `git config --global core.excludesFile` is empty, set one first:
> `git config --global core.excludesFile ~/.gitignore`.
A few configurations are incompatible with branch mode and are rejected at
create time:

You can also create Git worktrees yourself and run an agent directly in one,
but the sandbox won't have access to the `.git` directory in the parent
repository. This means the agent can't commit, push, or use Git. `--branch`
solves this by setting up the worktree so that Git works inside the sandbox.
- `--branch` together with `--workspace-volume`: the source-repository
isolation relies on bind-mounting your Git root, which is incompatible
with a volume-backed workspace.
- `--branch` from inside a host Git worktree: the bind mount can't resolve
the worktree's `.git` pointer file. Run `sbx create --branch ...` from
the main repository instead.

## Reconnecting and naming

Expand Down Expand Up @@ -250,8 +247,8 @@ $ sbx run claude-my-project

You can mount extra directories into a sandbox alongside the main workspace.
The first path is the primary workspace — the agent starts here, and the
sandbox's Git worktree is created from this directory if you use `--branch`.
Extra workspaces are always mounted directly.
sandbox's branch-mode clone is created from this directory if you use
`--branch`. Extra workspaces are always mounted directly.

All workspaces appear inside the sandbox at their absolute host paths. Append
`:ro` to mount an extra workspace read-only — useful for reference material or
Expand Down
Loading