Skip to content

Commit 0776d78

Browse files
authored
feat: redesign sandbox config (#1373)
This is a major redesign of how sandbox configuration works and aims to fix #1248. Specifically, it replaces `sandbox_permissions` in `config.toml` (and the `-s`/`--sandbox-permission` CLI flags) with a "table" with effectively three variants: ```toml # Safest option: full disk is read-only, but writes and network access are disallowed. [sandbox] mode = "read-only" # The cwd of the Codex task is writable, as well as $TMPDIR on macOS. # writable_roots can be used to specify additional writable folders. [sandbox] mode = "workspace-write" writable_roots = [] # Optional, defaults to the empty list. network_access = false # Optional, defaults to false. # Disable sandboxing: use at your own risk!!! [sandbox] mode = "danger-full-access" ``` This should make sandboxing easier to reason about. While we have dropped support for `-s`, the way it works now is: - no flags => `read-only` - `--full-auto` => `workspace-write` - currently, there is no way to specify `danger-full-access` via a CLI flag, but we will revisit that as part of #1254 Outstanding issue: - As noted in the `TODO` on `SandboxPolicy::is_unrestricted()`, we are still conflating sandbox preferences with approval preferences in that case, which needs to be cleaned up.
1 parent ed5e848 commit 0776d78

File tree

17 files changed

+199
-491
lines changed

17 files changed

+199
-491
lines changed

codex-rs/Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codex-rs/cli/src/debug_sandbox.rs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::path::PathBuf;
22

33
use codex_common::CliConfigOverrides;
4-
use codex_common::SandboxPermissionOption;
54
use codex_core::config::Config;
65
use codex_core::config::ConfigOverrides;
76
use codex_core::exec::StdioPolicy;
@@ -20,13 +19,11 @@ pub async fn run_command_under_seatbelt(
2019
) -> anyhow::Result<()> {
2120
let SeatbeltCommand {
2221
full_auto,
23-
sandbox,
2422
config_overrides,
2523
command,
2624
} = command;
2725
run_command_under_sandbox(
2826
full_auto,
29-
sandbox,
3027
command,
3128
config_overrides,
3229
codex_linux_sandbox_exe,
@@ -41,13 +38,11 @@ pub async fn run_command_under_landlock(
4138
) -> anyhow::Result<()> {
4239
let LandlockCommand {
4340
full_auto,
44-
sandbox,
4541
config_overrides,
4642
command,
4743
} = command;
4844
run_command_under_sandbox(
4945
full_auto,
50-
sandbox,
5146
command,
5247
config_overrides,
5348
codex_linux_sandbox_exe,
@@ -63,13 +58,12 @@ enum SandboxType {
6358

6459
async fn run_command_under_sandbox(
6560
full_auto: bool,
66-
sandbox: SandboxPermissionOption,
6761
command: Vec<String>,
6862
config_overrides: CliConfigOverrides,
6963
codex_linux_sandbox_exe: Option<PathBuf>,
7064
sandbox_type: SandboxType,
7165
) -> anyhow::Result<()> {
72-
let sandbox_policy = create_sandbox_policy(full_auto, sandbox);
66+
let sandbox_policy = create_sandbox_policy(full_auto);
7367
let cwd = std::env::current_dir()?;
7468
let config = Config::load_with_cli_overrides(
7569
config_overrides
@@ -110,13 +104,10 @@ async fn run_command_under_sandbox(
110104
handle_exit_status(status);
111105
}
112106

113-
pub fn create_sandbox_policy(full_auto: bool, sandbox: SandboxPermissionOption) -> SandboxPolicy {
107+
pub fn create_sandbox_policy(full_auto: bool) -> SandboxPolicy {
114108
if full_auto {
115-
SandboxPolicy::new_full_auto_policy()
109+
SandboxPolicy::new_workspace_write_policy()
116110
} else {
117-
match sandbox.permissions.map(Into::into) {
118-
Some(sandbox_policy) => sandbox_policy,
119-
None => SandboxPolicy::new_read_only_policy(),
120-
}
111+
SandboxPolicy::new_read_only_policy()
121112
}
122113
}

codex-rs/cli/src/lib.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,13 @@ pub mod proto;
55

66
use clap::Parser;
77
use codex_common::CliConfigOverrides;
8-
use codex_common::SandboxPermissionOption;
98

109
#[derive(Debug, Parser)]
1110
pub struct SeatbeltCommand {
1211
/// Convenience alias for low-friction sandboxed automatic execution (network-disabled sandbox that can write to cwd and TMPDIR)
1312
#[arg(long = "full-auto", default_value_t = false)]
1413
pub full_auto: bool,
1514

16-
#[clap(flatten)]
17-
pub sandbox: SandboxPermissionOption,
18-
1915
#[clap(skip)]
2016
pub config_overrides: CliConfigOverrides,
2117

@@ -30,9 +26,6 @@ pub struct LandlockCommand {
3026
#[arg(long = "full-auto", default_value_t = false)]
3127
pub full_auto: bool,
3228

33-
#[clap(flatten)]
34-
pub sandbox: SandboxPermissionOption,
35-
3629
#[clap(skip)]
3730
pub config_overrides: CliConfigOverrides,
3831

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
//! Standard type to use with the `--approval-mode` CLI option.
22
//! Available when the `cli` feature is enabled for the crate.
33
4-
use clap::ArgAction;
5-
use clap::Parser;
64
use clap::ValueEnum;
75

8-
use codex_core::config::parse_sandbox_permission_with_base_path;
96
use codex_core::protocol::AskForApproval;
10-
use codex_core::protocol::SandboxPermission;
117

128
#[derive(Clone, Copy, Debug, ValueEnum)]
139
#[value(rename_all = "kebab-case")]
@@ -36,38 +32,3 @@ impl From<ApprovalModeCliArg> for AskForApproval {
3632
}
3733
}
3834
}
39-
40-
#[derive(Parser, Debug)]
41-
pub struct SandboxPermissionOption {
42-
/// Specify this flag multiple times to specify the full set of permissions
43-
/// to grant to Codex.
44-
///
45-
/// ```shell
46-
/// codex -s disk-full-read-access \
47-
/// -s disk-write-cwd \
48-
/// -s disk-write-platform-user-temp-folder \
49-
/// -s disk-write-platform-global-temp-folder
50-
/// ```
51-
///
52-
/// Note disk-write-folder takes a value:
53-
///
54-
/// ```shell
55-
/// -s disk-write-folder=$HOME/.pyenv/shims
56-
/// ```
57-
///
58-
/// These permissions are quite broad and should be used with caution:
59-
///
60-
/// ```shell
61-
/// -s disk-full-write-access
62-
/// -s network-full-access
63-
/// ```
64-
#[arg(long = "sandbox-permission", short = 's', action = ArgAction::Append, value_parser = parse_sandbox_permission)]
65-
pub permissions: Option<Vec<SandboxPermission>>,
66-
}
67-
68-
/// Custom value-parser so we can keep the CLI surface small *and*
69-
/// still handle the parameterised `disk-write-folder` case.
70-
fn parse_sandbox_permission(raw: &str) -> std::io::Result<SandboxPermission> {
71-
let base_path = std::env::current_dir()?;
72-
parse_sandbox_permission_with_base_path(raw, base_path)
73-
}

codex-rs/common/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ pub mod elapsed;
66

77
#[cfg(feature = "cli")]
88
pub use approval_mode_cli_arg::ApprovalModeCliArg;
9-
#[cfg(feature = "cli")]
10-
pub use approval_mode_cli_arg::SandboxPermissionOption;
119

1210
#[cfg(any(feature = "cli", test))]
1311
mod config_override;

codex-rs/config.md

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ Here is an example of a `config.toml` that defines multiple profiles:
106106
```toml
107107
model = "o3"
108108
approval_policy = "unless-allow-listed"
109-
sandbox_permissions = ["disk-full-read-access"]
110109
disable_response_storage = false
111110

112111
# Setting `profile` is equivalent to specifying `--profile o3` on the command
@@ -170,31 +169,42 @@ To disable reasoning summaries, set `model_reasoning_summary` to `"none"` in you
170169
model_reasoning_summary = "none" # disable reasoning summaries
171170
```
172171

173-
## sandbox_permissions
172+
## sandbox
174173

175-
List of permissions to grant to the sandbox that Codex uses to execute untrusted commands:
174+
The `sandbox` configuration determines the _sandbox policy_ that Codex uses to execute untrusted commands. The `mode` determines the "base policy." Currently, only `workspace-write` supports additional configuration options, but this may change in the future.
175+
176+
The default policy is `read-only`, which means commands can read any file on disk, but attempts to write a file or access the network will be blocked.
176177

177178
```toml
178-
# This is comparable to --full-auto in the TypeScript Codex CLI, though
179-
# specifying `disk-write-platform-global-temp-folder` adds /tmp as a writable
180-
# folder in addition to $TMPDIR.
181-
sandbox_permissions = [
182-
"disk-full-read-access",
183-
"disk-write-platform-user-temp-folder",
184-
"disk-write-platform-global-temp-folder",
185-
"disk-write-cwd",
186-
]
179+
[sandbox]
180+
mode = "read-only"
187181
```
188182

189-
To add additional writable folders, use `disk-write-folder`, which takes a parameter (this can be specified multiple times):
183+
A more relaxed policy is `workspace-write`. When specified, the current working directory for the Codex task will be writable (as well as `$TMPDIR` on macOS). Note that the CLI defaults to using `cwd` where it was spawned, though this can be overridden using `--cwd/-C`.
190184

191185
```toml
192-
sandbox_permissions = [
193-
# ...
194-
"disk-write-folder=/Users/mbolin/.pyenv/shims",
186+
[sandbox]
187+
mode = "workspace-write"
188+
189+
# By default, only the cwd for the Codex session will be writable (and $TMPDIR on macOS),
190+
# but you can specify additional writable folders in this array.
191+
writable_roots = [
192+
"/tmp",
195193
]
194+
network_access = false # Like read-only, this also defaults to false and can be omitted.
196195
```
197196

197+
To disable sandboxing altogether, specify `danger-full-access` like so:
198+
199+
```toml
200+
[sandbox]
201+
mode = "danger-full-access"
202+
```
203+
204+
This is reasonable to use if Codex is running in an environment that provides its own sandboxing (such as a Docker container) such that further sandboxing is unnecessary.
205+
206+
Though using this option may also be necessary if you try to use Codex in environments where its native sandboxing mechanisms are unsupported, such as older Linux kernels or on Windows.
207+
198208
## mcp_servers
199209

200210
Defines the list of MCP servers that Codex can consult for tool use. Currently, only servers that are launched by executing a program that communicate over stdio are supported. For servers that use the SSE transport, consider an adapter like [mcp-proxy](https://github.com/sparfenyuk/mcp-proxy).

0 commit comments

Comments
 (0)