From 05ffa0b1d08170409f70037f96e356995d9b5b69 Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Fri, 8 May 2026 09:52:19 -0700 Subject: [PATCH] Fix `rust-ci-full` failures due to missing `bwrap` (#21604) Since https://github.com/openai/codex/pull/21255, `rust-ci-full` has been failing due to a missing `bwrap`. ``` thread 'main' panicked at linux-sandbox/src/launcher.rs:43:13: bubblewrap is unavailable: no system bwrap was found on PATH and no bundled codex-resources/bwrap binary was found next to the Codex executable ``` Since the happy path is now to use the system binary, let's ensure that's installed. https://github.com/openai/codex/pull/21604/commits/8d5182663158ee2d15965f39eed26ffa339ecb7d was necessary for the `bwrap` executable to be discoverable when the working directory is `/`. I ran `rust-ci-full` at https://github.com/openai/codex/actions/runs/25528074506 --------- Co-authored-by: Codex --- .github/workflows/rust-ci-full.yml | 2 +- codex-rs/sandboxing/src/bwrap.rs | 3 ++- codex-rs/sandboxing/src/bwrap_tests.rs | 14 ++++++++++++++ scripts/test-remote-env.sh | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust-ci-full.yml b/.github/workflows/rust-ci-full.yml index d0edf6751..6047bbdb6 100644 --- a/.github/workflows/rust-ci-full.yml +++ b/.github/workflows/rust-ci-full.yml @@ -567,7 +567,7 @@ jobs: set -euo pipefail if command -v apt-get >/dev/null 2>&1; then sudo apt-get update -y - sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends pkg-config libcap-dev + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends pkg-config libcap-dev bubblewrap fi # Some integration tests rely on DotSlash being installed. diff --git a/codex-rs/sandboxing/src/bwrap.rs b/codex-rs/sandboxing/src/bwrap.rs index e0eee177f..633487136 100644 --- a/codex-rs/sandboxing/src/bwrap.rs +++ b/codex-rs/sandboxing/src/bwrap.rs @@ -177,11 +177,12 @@ fn find_system_bwrap_in_search_paths( ) -> Option { let search_path = std::env::join_paths(search_paths).ok()?; let cwd = std::fs::canonicalize(cwd).unwrap_or_else(|_| cwd.to_path_buf()); + let cwd_is_root = cwd.parent().is_none(); which::which_in_all(SYSTEM_BWRAP_PROGRAM, Some(search_path), &cwd) .ok()? .find_map(|path| { let path = std::fs::canonicalize(path).ok()?; - if path.starts_with(&cwd) { + if !cwd_is_root && path.starts_with(&cwd) { None } else { Some(path) diff --git a/codex-rs/sandboxing/src/bwrap_tests.rs b/codex-rs/sandboxing/src/bwrap_tests.rs index 3c7a50392..d5fd9da43 100644 --- a/codex-rs/sandboxing/src/bwrap_tests.rs +++ b/codex-rs/sandboxing/src/bwrap_tests.rs @@ -149,6 +149,20 @@ fn skips_workspace_local_bwrap_in_joined_search_path() { ); } +#[test] +fn root_cwd_does_not_hide_system_bwrap_candidates() { + let temp_dir = tempdir().expect("temp dir"); + let bin_dir = temp_dir.path().join("bin"); + std::fs::create_dir_all(&bin_dir).expect("create bin dir"); + let expected_bwrap = write_named_fake_bwrap_in(&bin_dir); + let search_path = std::env::join_paths([bin_dir]).expect("join search path"); + + assert_eq!( + find_system_bwrap_in_search_paths(std::env::split_paths(&search_path), Path::new("/")), + Some(expected_bwrap) + ); +} + fn write_fake_bwrap(contents: &str) -> tempfile::TempPath { write_fake_bwrap_in( &std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")), diff --git a/scripts/test-remote-env.sh b/scripts/test-remote-env.sh index ba4d35f23..96743616a 100755 --- a/scripts/test-remote-env.sh +++ b/scripts/test-remote-env.sh @@ -59,7 +59,7 @@ setup_remote_env() { --privileged \ --security-opt seccomp=unconfined \ ubuntu:24.04 sleep infinity >/dev/null - if ! docker exec "${container_name}" sh -lc "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y python3 zsh"; then + if ! docker exec "${container_name}" sh -lc "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y python3 zsh bubblewrap"; then docker rm -f "${container_name}" >/dev/null 2>&1 || true return 1 fi