Skip to content
Merged
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
83 changes: 56 additions & 27 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ execute hostile projects or hostile instructions safely.
newly created workspace symlinks may not target paths outside that root.
Lexical inspection cannot prove every indirect effect of an arbitrary
program, so when an OS sandbox is available it also confines the writes and
the home-credential reads performed inside a command or script (see
[OS Write and Read Sandbox](#os-write-and-read-sandbox)). Bash is not a
complete sandbox: shell commands and invoked programs still run as the current
OS user, network is not confined in this stage, read confinement covers the
home secret locations rather than every workspace credential on every
platform, and the sandbox is absent when the backend is unavailable.
the home-credential reads performed inside a command or script, and — only for
`--offline` — the network (see
[OS Write, Read, and Network Sandbox](#os-write-read-and-network-sandbox)).
Bash is not a complete sandbox: shell commands and invoked programs still run
as the current OS user, network is confined only for `--offline` and only when
the backend is applied, read confinement covers the home secret locations
rather than every workspace credential on every platform, and the sandbox is
absent when the backend is unavailable.

## `--allow` and `--yes`

Expand All @@ -46,18 +48,40 @@ changes. At exit it reports the final tracked/staged diff stat and untracked
files. The report describes final workspace state and may include changes that
predated the run.

`--offline` blocks runtime dependency setup plus Bash command families named in
`--help`. It does not block provider/API requests or arbitrary network-capable
programs and therefore is not a network sandbox. Network isolation is a later
stage of #502 and is independent of the write sandbox below.

## OS Write and Read Sandbox

`--sandbox auto|required|off` (default `auto`) adds an OS-level write sandbox and
a home-credential read sandbox at the two `sh -c` launch points: the model Bash
tool (the `bash:verify` interval reuses the same function) and the
verification/acceptance commands. The sandbox is defense in depth; the lexical
checks still run first and can refuse a command before the shell starts.
`--offline` has two layers, and they are not the same guarantee.

- OS-blocked, when `--sandbox` applies a backend: outbound network connections
are refused by the OS, so an arbitrary program the lexical guard cannot name
(`python -c "urllib..."`, `node -e "fetch(...)"`) still cannot leave the
machine. macOS (Seatbelt) denies every network operation except loopback TCP
and unix sockets. Linux (Landlock ABI4, kernel 6.7) denies every TCP connect
except the run's dev-server port(s). Landlock matches the port only, so the
same port on an external host still connects and UDP is not restricted. When
the run's dev-server port cannot be derived — it is neither named in the goal
nor a profile default — the allow list is empty and every TCP connect is
denied, localhost included. Below ABI4 the network is not confined at all — the
`bash_sandbox_status` reason says so. The runtime dependency setup runs inside
this same sandbox, so a build backend (`setup.py`, an npm lifecycle script)
cannot write outside the workspace.
- Lexical-only, always: `--offline` refuses runtime dependency setup and the
Bash command families named in `--help` (npm/pnpm/yarn/cargo install, curl,
wget). These checks do not change when a backend is applied; they still run
first. Provider/API requests are CommandAgent's own traffic, outside the
sandbox, and remain enabled.

When `--sandbox` is `off` or its backend is unavailable, `--offline` is
lexical-only: it blocks the named command families but not an arbitrary
network-capable program.

## OS Write, Read, and Network Sandbox

`--sandbox auto|required|off` (default `auto`) adds an OS-level write sandbox, a
home-credential read sandbox, and (for `--offline`) a network sandbox at the
launch points the model can reach: the model Bash tool (the `bash:verify`
interval reuses the same function), the verification/acceptance commands, and
the runtime dependency setup (the Python `sh -c` and the `npm install`). The
sandbox is defense in depth; the lexical checks still run first and can refuse a
command before the shell starts.

- What the OS closes (when the backend is available): a write performed inside a
command or script that the lexical guard cannot see — `sh -c 'cp ...'`,
Expand Down Expand Up @@ -94,15 +118,20 @@ checks still run first and can refuse a command before the shell starts.
read on that secret's subtree, so the read layer cannot deny it; the status
then records that the read isolation is not effective instead of claiming it is
applied. An empty `HOME` is reported the same way.
- What remains lexical-only: network access, and every command run while the
backend is unavailable. `--allow bash:verify` and `--offline` are lexical
policies, so a command they admit can still start a script; only the sandbox
(when applied) constrains that script's writes and home-secret reads.
- Runtime dependency setup runs outside the sandbox: the setup steps that
execute `setup.py`, npm `postinstall`/`prepare` hooks, and similar
install-time scripts run before or outside the confined `sh -c` launch
points, so the sandbox does not constrain their writes. Confining dependency
setup is a later stage (#658).
- What remains lexical-only: every command run while the backend is
unavailable. `--allow bash:verify` and `--offline` are lexical policies, so a
command they admit can still start a script; only the sandbox (when applied)
constrains that script's writes, home-secret reads, and, for `--offline`,
network. The network a non-`--offline` run makes is unchanged (the lexical
guard alone applies), and an `--offline` network layer is OS-enforced only
when the backend is applied (see the `--offline` section above).
- Runtime dependency setup now runs inside the sandbox (Issue #658): the
Python `sh -c` (venv and `pip install -e .`, including `setup.py`) and the
`npm install` are wrapped like the model Bash launches, so an install-time
script cannot write outside the workspace. With `auto` and an unavailable
backend the setup runs outside the sandbox as before and the
`bash_sandbox_status` record says it is not applied; with `required` it fails
honestly.
- A hardlink that already exists in the workspace before the run and points at
an inode outside the workspace can still be written through. Seatbelt decides
by path, so it allows writing the workspace path even though the inode lives
Expand Down
40 changes: 27 additions & 13 deletions docs/guide/en/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ internal integration surface and is intentionally not a public user flag.
| `--profile` | `<PROFILE>` | inferred, then `generic` | Set a compiled profile or an external draft ID. An external ID requires the extension root that declares `profiles/<id>/manifest.toml`. | [Profile inference](slash-commands.md#profile-inference) |
| `--style` | `<STYLE>` | `default` | Pass the plan presentation/generation style. | [Inline flags](slash-commands.md#inline-flags) |
| `--resume` | `<RESUME>` | none | Load the named saved minimal-loop session for a direct `--prompt` run. | [Session options](#conflicts-and-combinations) |
| `--offline` | none | off | Block runtime dependency setup and Bash commands containing npm/pnpm/yarn/cargo install, curl, or wget. Provider/API requests and other network-capable commands are unaffected. | [Providers](providers.md) |
| `--sandbox` | `<auto\|required\|off>` | `auto` | Select the OS write sandbox for Bash and verifier commands. `auto` applies it when the backend is available and otherwise continues with lexical checks only; `required` fails those commands when the backend is unavailable; `off` keeps the previous behavior. | [OS write and read sandbox](#os-write-and-read-sandbox) |
| `--offline` | none | off | Block runtime dependency setup and Bash commands containing npm/pnpm/yarn/cargo install, curl, or wget. Provider/API requests and other network-capable commands are unaffected. | [OS write, read, and network sandbox](#os-write-read-and-network-sandbox) |
| `--sandbox` | `<auto\|required\|off>` | `auto` | Select the OS write sandbox for Bash and verifier commands. `auto` applies it when the backend is available and otherwise continues with lexical checks only; `required` fails those commands when the backend is unavailable; `off` keeps the previous behavior. | [OS write, read, and network sandbox](#os-write-read-and-network-sandbox) |
| `--quiet` | none | off (`narration = "normal"`) | Suppress presentation narration. | [Top-level keys](configuration.md#top-level-keys) |
| `--summary-json` | none | off | Append one machine-readable terminal run summary as the final stdout line. Omitting it preserves existing stdout bytes. | [Headless execution](../../user/headless.md) |
| `--trace` | none | off | Opt in to scrubbed provider request and response traces under the active run directory. | [Troubleshooting](troubleshooting.md) |
Expand All @@ -98,16 +98,19 @@ internal integration surface and is intentionally not a public user flag.
| `--footer` | `<on\|off>` | `on` | Control the fixed TUI footer; off keeps scrollback breadcrumbs. | [Footer problems](troubleshooting.md#footer-rendering-problems) |
| `--no-footer` | none | off | Disable the fixed TUI footer. Equivalent in effect to `--footer off`. | [Footer problems](troubleshooting.md#footer-rendering-problems) |

## OS write and read sandbox
## OS write, read, and network sandbox

The `--sandbox auto|required|off` flag (default `auto`) controls an OS-level
write sandbox and a home-credential read sandbox for the model Bash tool and for
verification/acceptance commands. The lexical checks still run first; the
sandbox adds confinement for writes and reads the lexical guard cannot see.
write sandbox, a home-credential read sandbox, and (for `--offline`) a network
sandbox for the model Bash tool, verification/acceptance commands, and the
runtime dependency setup (the Python `sh -c` and the `npm install`). The lexical
checks still run first; the sandbox adds confinement for the writes, reads, and
(with `--offline`) network the lexical guard cannot see.

- **What the OS closes (when the backend is available):** writes performed inside
a command or script — `sh -c 'cp ...'`, `eval`, `xargs`, `find -exec`, an
interpreter's `open(..., 'w')`, `dd of=`, `sed -i` — and hardlinks to an inode
interpreter's `open(..., 'w')`, `dd of=`, `sed -i`, and an install-time script
such as `setup.py` or an npm lifecycle script — and hardlinks to an inode
outside the workspace. Only the workspace, the run's temp directory, the known
dependency caches, and device files such as `/dev/null` are writable.
- **Read confinement:** reading the home secret locations (`.ssh`, `.aws`,
Expand All @@ -128,12 +131,23 @@ sandbox adds confinement for writes and reads the lexical guard cannot see.
read layer cannot deny those secrets, and the status says the read isolation is
not effective instead of claiming it is applied; an empty `HOME` is reported
the same way.
- **What stays lexical-only:** network access, and every command run when the
backend is unavailable. `--yes`, `--allow bash:verify`, and `--offline` do not
close an indirect write or a home-secret read by themselves; only the sandbox,
when applied, does. `--allow bash:verify` admits a command by its
classification only, so the contents of any script it invokes are limited by
the sandbox alone.
- **Network (`--offline` only):** when the backend is applied, an `--offline`
run has its outbound connections refused by the OS, so an arbitrary program the
lexical guard cannot name (`python -c "urllib..."`, `node -e "fetch(...)"`)
cannot reach the network. macOS denies every network operation except loopback
TCP and unix sockets. Linux (Landlock ABI4, kernel 6.7) denies every TCP
connect except the run's dev-server port(s): Landlock matches the port only, so
the same port on an external host still connects and UDP is not restricted, and
below ABI4 the network is not confined — the `bash_sandbox_status` reason says
so. A run that is not `--offline` is unchanged.
- **What stays lexical-only:** every command run when the backend is unavailable.
`--yes`, `--allow bash:verify`, and `--offline` do not close an indirect write
or a home-secret read by themselves; only the sandbox, when applied, does.
`--allow bash:verify` admits a command by its classification only, so the
contents of any script it invokes are limited by the sandbox alone. With `auto`
and an unavailable backend the dependency setup runs outside the sandbox as
before and the status records it as not applied; with `required` it fails
honestly.
- **Modes:** `auto` uses the backend when available and otherwise warns once and
records `bash_sandbox_status` with `applied=false` and a reason, continuing
with lexical checks only; `required` fails Bash and verifier commands with
Expand Down
Loading
Loading