Finalize `sandbox_permissions` configuration option

Resolved 💬 7 comments Opened Jun 6, 2025 by bolinfest Closed Jun 24, 2025
💡 Likely answer: A maintainer (bolinfest, collaborator) responded on this thread — see the highlighted reply below.

Originally, the TypeScript CLI tried to provide a simple set of sandboxing/approval options: --suggest, --auto-edit, and --full-auto. We shortly discovered that we were conflating two concepts: approvals and sandboxing, which we worked to separate in the Rust CLI.

In an attempt to provide flexibility, we introduced more fine-grained sandbox permissions in the Rust CLI that could be specified individually where --sandbox-permission could be specified multiple times. This has confused people because doing --sandbox-permission network-full-access would "reset" all of your permissions and include only network-full-access, losing permissions such as disk-full-read-access, which is almost never what the user wants.

It also makes the TUI really noisy, as the start of the conversation includes something verbose like:

sandbox: SandboxPolicy { permissions: [DiskFullReadAccess, DiskWritePlatformUserTempFolder, DiskWritePlatformGlobalTempFolder, DiskWriteCwd }

Ideally, we would have something that:

  • Affords a simple flag for the common case (e.g., --full-auto) that can also be expressed succinctly in config.toml so users don't have to pass the simple flag each time.
  • Affords more fine-grained configuration without as much risk of users shooting themselves in the foot.
  • Can be expressed succinctly at the start of a session so the user is clear what aggregate sandbox config they ended up with.

View original on GitHub ↗

7 Comments

bolinfest collaborator · 1 year ago

I think a good solution to this problem would have the following properties:

  • Supports having a preset (like --full-auto) to use as a "base configuration," to which additional rules can be applied on top. These "additional rules" can add or remove priviliges.
  • Produces an internal sandbox policy abstraction that can be directly translated into rules that both Seatbelt and Landlock can implement.
  • Also has a succinct way of declaring "do not run commands in a sandbox [because my execution environment provides sufficient sandbox guarantees and/or I am choosing to take the risk of not using a sandbox]."
  • Introduces one flag (that can be specified multiple times and have a complex type) to the CLI instead of having individual flags for each permission type.
  • Can be expressed succinctly in config.toml.
bolinfest collaborator · 1 year ago

In principle, we have three types of permissions today:

  • disk read
  • disk write
  • network access

Roughly, each permission could have "three" settings:

  • full
  • none
  • custom

Though certainly "custom" is where things get dicey. Currently, we do not even support "custom" configuration for disk read or network access (only all or nothing), but the customization for disk write is a bit complicated because we support specifying exact folders as well as more "declarative" type things like disk-write-cwd.

bolinfest collaborator · 1 year ago

Spitballing, perhaps introducing support for enable- and disable- prefixes would make it more straightforward to build on top of a sandbox preset:

--full-auto -s enable-disk-write-platform-user-temp-folder -s enable-disk-write-folder=/Users/mbolin/.pyenv/shims

though then perhaps the TOML would have to look something like:

sandbox_base = "full-auto"

sandbox_permissions = [
    "enable-disk-write-platform-user-temp-folder",
    "enable-disk-write-folder=/Users/mbolin/.pyenv/shims",
]

which seems distasteful.

It also reinforces this issue where --full-auto is overloaded to provide a base config for both sandboxing and approvals.

Maybe something more like:

# Use a read-only sandbox.
-s read-only-preset

# World readable, only cwd is writable, network disabled, and then include two additional writable folders.
-s write-cwd-preset -s enable-disk-write-platform-user-temp-folder -s enable-disk-write-folder=/Users/mbolin/.pyenv/shims

# Commands are never run inside a sandbox.
-s dangerously-operate-without-a-sandbox-preset

In this scheme, the TOML has one sandbox-related config option, which is always a list:

sandbox = [
    "write-cwd-preset",
    "enable-disk-write-platform-user-temp-folder",
    "enable-disk-write-folder=/Users/mbolin/.pyenv/shims",
]

Note that overriding sandbox as defined in config.toml on the command line would effectively be easier to do via -s than via -c because -c would only support redefining sandbox outright rather than amending entries to the existing list.

bolinfest collaborator · 1 year ago

In other words, -s args would have to satisfy one of the following conditions:

  • start with enable-
  • start with disable-
  • end with -preset

In the header in the TUI, the sandbox entry would likely be more succinct than it is today since we wouldn't expand the preset definition there.

We would also have to define what happens if multiple preset- values are passed via -s as well as what happens if -s dangerously-operate-without-a-sandbox-preset is used in combination with disable- options...

bolinfest collaborator · 1 year ago

Revisiting this issue, I think my last proposal is too verbose. For example, there should be a limited set of presets, so the -preset suffix should be unnecessary since we can ensure their names not overlap with other options. Similarly, enable- should be far more common than disable-, so we should omit the enable- prefix, as it should be an implicit default.

In practice, today we have three "sandbox presets" that we want to support:

  • global read; no writes; no network
  • global read; write cwd [and tmp?]; no network
  • no sandbox

In terms of "relaxing" the sandbox, the only thing we really let you do is add more writable roots. (Though we might want to let users enable network while still limiting writes?)

As far as naming these preset modes, we could go with:

  • read-only
  • workspace-write
  • danger-full-access

And perhaps to simplify things, we require a "base mode" (defaults to read-only) and any further sandbox permissions must be "additive" to the mode that was originally specified.

bolinfest collaborator · 1 year ago

Here is a simpler scheme:

  • specify sandbox mode, one of: read-only, workspace-write, danger-full-access
  • users can specify additional writable roots (ignored in danger-full-access mode)
  • users can enable network (ignored in danger-full-access mode)

For now, there is no way to disable global read-only access (or restrict it to a specific set of folders), but we can consider that later, if appropriate.

In the config file, this would look like:

# Defaults to "read-only". Can specify via CLI using `-s/--sandbox MODE`.
sandbox = "workspace-write"  # or "read-only" or "danger-full-access"

# Optional list. Can add to list via CLI `--sandbox-writable-root PATH`.
# Seems rare enough that it does not need a short-form arg name?
sandbox_writable_roots = [
    "/Users/mbolin/.pyenv/shims",
    "/tmp",
]

# Defaults to false. For now, no special CLI arg, though the more generic `-c sandbox_network_access=true` will work.
sandbox_network_access = true
bolinfest collaborator · 1 year ago

Upon further consideration, a better config file format is probably:

[sandbox]
mode = "workspace-write"
writable_roots = ["/tmp"]
network_access = true