Compare commits

...

3 Commits

Author SHA1 Message Date
Jeremy Rose
77e8a45684 Merge branch 'main' into nornagon/fix-openpty-test 2025-12-11 15:12:10 -08:00
Jeremy Rose
7ea7634735 Update codex-rs/exec/Cargo.toml 2025-12-03 10:31:00 -08:00
Jeremy Rose
2d50c0a865 core(sandbox): fix openpty test 2025-12-03 10:21:31 -08:00
4 changed files with 49 additions and 46 deletions

1
codex-rs/Cargo.lock generated
View File

@@ -1201,6 +1201,7 @@ dependencies = [
"ts-rs",
"uuid",
"walkdir",
"which",
"wiremock",
]

View File

@@ -159,18 +159,23 @@ async fn read_only_forbids_all_writes() {
.await;
}
/// Verify that user lookups via `pwd.getpwuid(os.getuid())` work under the
/// seatbelt sandbox. Prior to allowing the necessary machlookup for
/// OpenDirectory libinfo, this would fail with `KeyError: getpwuid(): uid not found`.
#[tokio::test]
async fn openpty_works_under_seatbelt() {
async fn python_getpwuid_works_under_seatbelt() {
if std::env::var(CODEX_SANDBOX_ENV_VAR) == Ok("seatbelt".to_string()) {
eprintln!("{CODEX_SANDBOX_ENV_VAR} is set to 'seatbelt', skipping test.");
return;
}
// For local dev.
if which::which("python3").is_err() {
eprintln!("python3 not found in PATH, skipping test.");
return;
}
// ReadOnly is sufficient here since we are only exercising user lookup.
let policy = SandboxPolicy::ReadOnly;
let command_cwd = std::env::current_dir().expect("getcwd");
let sandbox_cwd = command_cwd.clone();
@@ -179,12 +184,8 @@ async fn openpty_works_under_seatbelt() {
vec![
"python3".to_string(),
"-c".to_string(),
r#"import os
master, slave = os.openpty()
os.write(slave, b"ping")
assert os.read(master, 4) == b"ping""#
.to_string(),
// Print the passwd struct; success implies lookup worked.
"import pwd, os; print(pwd.getpwuid(os.getuid()))".to_string(),
],
command_cwd,
&policy,

View File

@@ -59,4 +59,5 @@ pretty_assertions = { workspace = true }
tempfile = { workspace = true }
uuid = { workspace = true }
walkdir = { workspace = true }
which = { workspace = true }
wiremock = { workspace = true }

View File

@@ -109,45 +109,6 @@ if __name__ == '__main__':
assert!(status.success(), "python exited with {status:?}");
}
#[tokio::test]
async fn python_getpwuid_works_under_sandbox() {
core_test_support::skip_if_sandbox!();
if std::process::Command::new("python3")
.arg("--version")
.status()
.is_err()
{
eprintln!("python3 not found in PATH, skipping test.");
return;
}
let policy = SandboxPolicy::ReadOnly;
let command_cwd = std::env::current_dir().expect("should be able to get current dir");
let sandbox_cwd = command_cwd.clone();
let mut child = spawn_command_under_sandbox(
vec![
"python3".to_string(),
"-c".to_string(),
"import pwd, os; print(pwd.getpwuid(os.getuid()))".to_string(),
],
command_cwd,
&policy,
sandbox_cwd.as_path(),
StdioPolicy::RedirectForShellTool,
HashMap::new(),
)
.await
.expect("should be able to spawn python under sandbox");
let status = child
.wait()
.await
.expect("should be able to wait for child process");
assert!(status.success(), "python exited with {status:?}");
}
#[tokio::test]
async fn sandbox_distinguishes_command_and_policy_cwds() {
core_test_support::skip_if_sandbox!();
@@ -315,6 +276,45 @@ async fn allow_unix_socketpair_recvfrom() {
.expect("should be able to reexec");
}
#[tokio::test]
async fn openpty_works_under_seatbelt() {
core_test_support::skip_if_sandbox!();
if which::which("python3").is_err() {
eprintln!("python3 not found in PATH, skipping test.");
return;
}
let policy = SandboxPolicy::ReadOnly;
let command_cwd = std::env::current_dir().expect("getcwd");
let sandbox_cwd = command_cwd.clone();
let mut child = spawn_command_under_sandbox(
vec![
"python3".to_string(),
"-c".to_string(),
r#"import os
master, slave = os.openpty()
os.write(slave, b"ping")
assert os.read(master, 4) == b"ping""#
.to_string(),
],
command_cwd,
&policy,
sandbox_cwd.as_path(),
StdioPolicy::RedirectForShellTool,
HashMap::new(),
)
.await
.expect("should be able to spawn python under sandbox");
let status = child
.wait()
.await
.expect("should be able to wait for child process");
assert!(status.success(), "python exited with {status:?}");
}
const IN_SANDBOX_ENV_VAR: &str = "IN_SANDBOX";
#[expect(clippy::expect_used)]