Skip to content
Open
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
4 changes: 4 additions & 0 deletions codex-rs/core/src/seatbelt_base_policy.sbpl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
(allow process-fork)
(allow signal (target same-sandbox))

; Permit /bin/ps to run without sandboxing so Homebrew's `brew shellenv`
; can detect the shell even though /bin/ps is setuid.
(allow process-exec (path "/bin/ps") (with no-sandbox))

; Allow cf prefs to work.
(allow user-preference-read)

Expand Down
49 changes: 49 additions & 0 deletions codex-rs/core/tests/suite/seatbelt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,55 @@ async fn python_getpwuid_works_under_seatbelt() {
assert!(status.success(), "python exited with {status:?}");
}

#[tokio::test]
async fn brew_shellenv_runs_under_seatbelt_workspace_write_policy() {
if std::env::var(CODEX_SANDBOX_ENV_VAR) == Ok("seatbelt".to_string()) {
eprintln!("{CODEX_SANDBOX_ENV_VAR} is set to 'seatbelt', skipping test.");
return;
}

let Ok(brew_path) = which::which("brew") else {
eprintln!("brew not found in PATH, skipping test.");
return;
};

let policy = SandboxPolicy::new_workspace_write_policy();
let command_cwd = std::env::current_dir().expect("getcwd");
let sandbox_cwd = command_cwd.clone();

let mut env: HashMap<String, String> = std::env::vars().collect();
env.remove(CODEX_SANDBOX_ENV_VAR);

let child = spawn_command_under_seatbelt(
vec![
brew_path.to_string_lossy().to_string(),
"shellenv".to_string(),
],
command_cwd,
&policy,
sandbox_cwd.as_path(),
StdioPolicy::RedirectForShellTool,
env,
)
.await
.expect("should be able to spawn brew shellenv under seatbelt");

let output = child
.wait_with_output()
.await
.expect("should be able to wait for brew shellenv child");
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
output.status.success(),
"brew shellenv under seatbelt exited with {:?}, stderr: {stderr}",
output.status
);
assert!(
!stderr.contains("Operation not permitted"),
"brew shellenv under seatbelt should not hit permission errors, stderr: {stderr}"
);
}

#[tokio::test]
async fn java_home_finds_runtime_under_seatbelt() {
if std::env::var(CODEX_SANDBOX_ENV_VAR) == Ok("seatbelt".to_string()) {
Expand Down
Loading