fix: introduce AbsolutePathBuf as part of sandbox config (#7856)

Changes the `writable_roots` field of the `WorkspaceWrite` variant of
the `SandboxPolicy` enum from `Vec<PathBuf>` to `Vec<AbsolutePathBuf>`.
This is helpful because now callers can be sure the value is an absolute
path rather than a relative one. (Though when using an absolute path in
a Seatbelt config policy, we still have to _canonicalize_ it first.)

Because `writable_roots` can be read from a config file, it is important
that we are able to resolve relative paths properly using the parent
folder of the config file as the base path.
This commit is contained in:
Michael Bolin
2025-12-12 15:25:22 -08:00
committed by GitHub
parent 3d07cd6c0c
commit 642b7566df
34 changed files with 277 additions and 122 deletions

View File

@@ -14,6 +14,7 @@ use codex_protocol::config_types::ReasoningSummary;
use codex_protocol::config_types::SandboxMode;
use codex_protocol::config_types::Verbosity;
use codex_protocol::openai_models::ReasoningEffort;
use codex_utils_absolute_path::AbsolutePathBuf;
use pretty_assertions::assert_eq;
use std::collections::HashMap;
use std::path::Path;
@@ -23,10 +24,16 @@ use tokio::time::timeout;
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
fn create_config_toml(codex_home: &Path) -> std::io::Result<()> {
let writable_root = if cfg!(windows) {
r"C:\Users\codex\AppData\Local\Temp"
} else {
"/tmp"
};
let config_toml = codex_home.join("config.toml");
std::fs::write(
config_toml,
r#"
format!(
r#"
model = "gpt-5.1-codex-max"
approval_policy = "on-request"
sandbox_mode = "workspace-write"
@@ -38,7 +45,7 @@ forced_chatgpt_workspace_id = "12345678-0000-0000-0000-000000000000"
forced_login_method = "chatgpt"
[sandbox_workspace_write]
writable_roots = ["/tmp"]
writable_roots = [{}]
network_access = true
exclude_tmpdir_env_var = true
exclude_slash_tmp = true
@@ -56,6 +63,8 @@ model_verbosity = "medium"
model_provider = "openai"
chatgpt_base_url = "https://api.chatgpt.com"
"#,
serde_json::json!(writable_root)
),
)
}
@@ -75,12 +84,18 @@ async fn get_config_toml_parses_all_fields() -> Result<()> {
.await??;
let config: GetUserSavedConfigResponse = to_response(resp)?;
let writable_root = if cfg!(windows) {
r"C:\Users\codex\AppData\Local\Temp"
} else {
"/tmp"
};
let writable_root = AbsolutePathBuf::from_absolute_path(writable_root)?;
let expected = GetUserSavedConfigResponse {
config: UserSavedConfig {
approval_policy: Some(AskForApproval::OnRequest),
sandbox_mode: Some(SandboxMode::WorkspaceWrite),
sandbox_settings: Some(SandboxSettings {
writable_roots: vec!["/tmp".into()],
writable_roots: vec![writable_root],
network_access: Some(true),
exclude_tmpdir_env_var: Some(true),
exclude_slash_tmp: Some(true),