Skip to main content
Status: engine and the switch are in; the blocked-write card is not yet. The boundary (host-side write checks + macOS Seatbelt wrapping), the fail-closed rule, session-preference persistence and the composer lock chip all work today (with unit tests and a real-machine check). What is still missing is the card that offers “allow once / remember this directory” when a write is blocked — for now a block surfaces as a tool error the model can act on. The default is still full-access.
Permission presets answer “does it ask first?”. The sandbox mode answers “will the kernel allow it at all?” They are orthogonal: an approval (or an AI review) cannot cross the sandbox, and a sandboxed write never even reaches an approval card.
Off by default on purpose: the biggest risk of a sandbox is not bypass, it is breaking normal work for no visible reason. Collect the false-positive list before turning it on by default.

The three modes

The workspace-write allow set = workspace + write roots you recorded in .kova/permissions*.json + platform temp directories + a toolchain cache allow-list (~/.bun/install/cache, ~/.npm, ~/.cache, ~/.cargo/registry, ~/Library/Caches, ~/Library/pnpm, ~/.yarn/berry/cache, ~/go/pkg/mod, ~/.gradle/caches, ~/.m2/repository, …). Miss one entry and installs start failing — that is the most common “it broke for no reason” case. Two fixed rules:
  • Reads stay open. read-only means “cannot write”, not “cannot look”; it is not confidentiality isolation.
  • .env / .env.* / *.pem / *.key never land on disk (denyWrite, hard refusal without a prompt).

Where the boundary is enforced

The order is deny → allow → refuse. Refusals come back as tool errors that tell the model what to do instead (write inside the workspace, or ask the user to add a write root).

Fail closed

If the sandbox cannot start (missing ripgrep, unsupported platform, profile generation failed), the command is not executed and the error names the reason and the way out. Never a silent unsandboxed fallback: “thought it was isolated when it was not” is far worse than “this step failed”.

How it relates to the other two mechanisms

  • Approval decides whether you are asked;
  • AI review lets the model decide instead of you;
  • The sandbox decides how far an allowed call can reach.
So you can run “Full access” with workspace isolation on: no interruptions, and still no writes outside the workspace.

How to switch it

In the composer toolbar, to the right of the permission picker, there is a lock: closed with a shield = workspace isolation, a blue closed lock = read-only, open lock = no sandbox. Click it to switch; the choice is a session preference (survives reloads) and new sessions follow your last pick. full-access is the default, so you have to switch once to actually enable isolation.

Known limits

  • macOS only for subprocess isolation in this version; other platforms report an honest error instead of pretending to isolate.
  • MCP server processes are not wrapped yet; write/edit and bash are.
  • No network policy yet (file isolation only).
  • The sandbox cannot read intent — it only looks at paths. To stop it from refusing something legitimate, add that root to the write-roots list (the same list “Workspace-write” uses).

Next

The sandbox and its three neighbours: session mode, permission presets, automation policy.