exec-server: preserve fs helper runtime env (#18380)

## Summary
- preserve a small fs-helper runtime env allowlist (`PATH`, temp vars)
instead of launching the sandboxed helper with an empty env
- add unit coverage for the allowlist and transformed sandbox request
env
- add a Linux smoke test that starts the test exec-server with a fake
`bwrap` on `PATH`, runs a sandboxed fs write through the remote fs
helper path, and asserts that bwrap path was exercised

## Validation
- `cd /tmp/codex-worktrees/fs-helper-env-defaults/codex-rs && export
PATH=$HOME/code/openai/project/dotslash-gen/bin:$HOME/.local/bin:$PATH
&& bazel test --bes_backend= --bes_results_url=
//codex-rs/exec-server:exec-server-file_system-test
--test_filter=sandboxed_file_system_helper_finds_bwrap_on_preserved_path`
- `cd /tmp/codex-worktrees/fs-helper-env-defaults/codex-rs && export
PATH=$HOME/code/openai/project/dotslash-gen/bin:$HOME/.local/bin:$PATH
&& bazel test --bes_backend= --bes_results_url=
//codex-rs/exec-server:exec-server-unit-tests
--test_filter="helper_env|sandbox_exec_request_carries_helper_env"`
- earlier on this branch before the smoke-test harness adjustment: `cd
/tmp/codex-worktrees/fs-helper-env-defaults/codex-rs && export
PATH=$HOME/code/openai/project/dotslash-gen/bin:$HOME/.local/bin:$PATH
&& bazel test --bes_backend= --bes_results_url=
//codex-rs/exec-server:all`

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
starr-openai
2026-04-17 13:44:01 -07:00
committed by GitHub
parent 139fa8b8f2
commit 63e4a900c9
3 changed files with 233 additions and 2 deletions

View File

@@ -2,6 +2,8 @@
mod common;
#[cfg(target_os = "linux")]
use std::os::unix::fs::PermissionsExt;
use std::os::unix::fs::symlink;
use std::path::Path;
use std::path::PathBuf;
@@ -31,6 +33,8 @@ use test_case::test_case;
use common::exec_server::ExecServerHarness;
use common::exec_server::TestCodexHelperPaths;
use common::exec_server::exec_server;
#[cfg(target_os = "linux")]
use common::exec_server::exec_server_with_env;
use common::exec_server::test_codex_helper_paths;
struct FileSystemContext {
@@ -148,6 +152,96 @@ fn alias_root_candidate() -> Result<Option<PathBuf>> {
Ok(None)
}
#[cfg(target_os = "linux")]
fn write_fake_bwrap(bin_dir: &Path) -> Result<PathBuf> {
std::fs::create_dir_all(bin_dir)?;
let fake_bwrap = bin_dir.join("bwrap");
std::fs::write(
&fake_bwrap,
r#"#!/bin/bash
set -euo pipefail
for arg in "$@"; do
if [[ "${arg}" == "--help" ]]; then
echo "Usage: bwrap --argv0"
exit 0
fi
done
printf '%s\n' "$*" >> "${0}.log"
args=("$@")
argv0=""
command_start=-1
for i in "${!args[@]}"; do
if [[ "${args[$i]}" == "--argv0" && $((i + 1)) -lt ${#args[@]} ]]; then
argv0="${args[$((i + 1))]}"
fi
if [[ "${args[$i]}" == "--" ]]; then
command_start=$((i + 1))
break
fi
done
if [[ "${command_start}" -lt 0 || "${command_start}" -ge "${#args[@]}" ]]; then
echo "fake bwrap did not find an inner command" >&2
exit 125
fi
cmd=("${args[@]:$command_start}")
if [[ -n "${argv0}" ]]; then
exec -a "${argv0}" "${cmd[@]}"
fi
exec "${cmd[@]}"
"#,
)?;
let mut permissions = std::fs::metadata(&fake_bwrap)?.permissions();
permissions.set_mode(0o755);
std::fs::set_permissions(&fake_bwrap, permissions)?;
Ok(fake_bwrap)
}
#[cfg(target_os = "linux")]
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn sandboxed_file_system_helper_finds_bwrap_on_preserved_path() -> Result<()> {
let tmp = TempDir::new()?;
let fake_bin_dir = tmp.path().join("bin");
let fake_bwrap = write_fake_bwrap(&fake_bin_dir)?;
let mut path_entries = vec![fake_bin_dir];
if let Some(path) = std::env::var_os("PATH") {
path_entries.extend(std::env::split_paths(&path));
}
let helper_path = std::env::join_paths(path_entries)?;
let server = exec_server_with_env([("PATH", helper_path.as_os_str())]).await?;
let environment = Environment::create(Some(server.websocket_url().to_string())).await?;
let file_system = environment.get_filesystem();
let workspace = tmp.path().join("workspace");
std::fs::create_dir_all(&workspace)?;
let file_path = workspace.join("created.txt");
let sandbox = workspace_write_sandbox(workspace);
file_system
.write_file(
&absolute_path(file_path.clone()),
b"written through fs helper".to_vec(),
Some(&sandbox),
)
.await?;
assert_eq!(std::fs::read(&file_path)?, b"written through fs helper");
let bwrap_log = fake_bwrap.with_file_name("bwrap.log");
let log = std::fs::read_to_string(&bwrap_log)
.with_context(|| format!("expected fake bwrap log at {}", bwrap_log.display()))?;
assert!(
log.contains("--argv0"),
"expected fs helper sandbox path to invoke PATH bwrap with --argv0, got: {log}"
);
Ok(())
}
#[test_case(false ; "local")]
#[test_case(true ; "remote")]
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]