openai/codex · critical
invalid bundled bubblewrap fd path: {err}
Error message
invalid bundled bubblewrap fd path: {err} What it means
After digest verification, exec() runs bwrap through its /proc/self/fd/{fd} path so the exact verified file (not a re-resolvable path) is executed. That generated path is converted to a CString; the panic fires only if the string contains an interior NUL byte, which is impossible for the literal prefix /proc/self/fd/ followed by a decimal fd number. It is a defensive assertion guarding an effectively unreachable condition.
Source
Thrown at codex-rs/linux-sandbox/src/bundled_bwrap.rs:52
impl BundledBwrapLauncher {
pub(crate) fn exec(&self, argv: Vec<String>, preserved_files: Vec<File>) -> ! {
let bwrap_file = File::open(self.program.as_path()).unwrap_or_else(|err| {
panic!(
"failed to open bundled bubblewrap {}: {err}",
self.program.as_path().display()
)
});
if let Err(err) = verify_digest(&bwrap_file, expected_sha256(), self.program.as_path()) {
eprintln!("{err}");
std::process::exit(crate::BUNDLED_BWRAP_DIGEST_VERIFICATION_FAILURE_EXIT_CODE);
}
make_files_inheritable(&preserved_files);
let fd_path = format!("/proc/self/fd/{}", bwrap_file.as_raw_fd());
let program_cstring = CString::new(fd_path.as_str())
.unwrap_or_else(|err| panic!("invalid bundled bubblewrap fd path: {err}"));
let cstrings = argv_to_cstrings(&argv);
let mut argv_ptrs: Vec<*const c_char> = cstrings
.iter()
.map(CString::as_c_str)
.map(CStr::as_ptr)
.collect();
argv_ptrs.push(std::ptr::null());
// SAFETY: `program_cstring` and every entry in `argv_ptrs` are valid C
// strings for the duration of the call. On success `execv` does not return.
unsafe {
libc::execv(program_cstring.as_ptr(), argv_ptrs.as_ptr());
}
let err = std::io::Error::last_os_error();
panic!(
"failed to exec bundled bubblewrap {} via {fd_path}: {err}",
self.program.as_path().display()
);View on GitHub (pinned to 339751715c)
Solutions
- Treat as an environment or binary integrity failure: rebuild from clean sources and re-verify the installation.
- Report upstream with the exact panic message and platform details; no correct caller code can trigger this path.
Defensive patterns
Strategy: validation
Validate before calling
// Defensive: reject paths with interior NUL bytes before any exec-style API
fn cstring_safe(s: &str) -> bool {
!s.contains('\u{0}')
}
assert!(cstring_safe(program_path.to_str().unwrap_or(""))); Type guard
fn is_cstring_safe(s: &str) -> bool { !s.contains('\u{0}') } Prevention
- No caller-side action can trigger this panic; it guards an impossible condition.
- Keep toolchain and binary provenance verifiable (reproducible builds) so corruption is detectable.
When it happens
Trigger: Not reachable through normal API use: the fd path is synthesized from a raw descriptor number. A hit indicates memory corruption, a patched/incompatible runtime, or a corrupted build rather than caller error.
Common situations: None in practice; would only surface under fuzzing, binary corruption, or a runtime tampering with format!/CString internals.
Related errors
- failed to open bundled bubblewrap {}: {err}
- failed to exec bundled bubblewrap {} via {fd_path}: {err}
- failed to normalize bundled bubblewrap path {}: {err}
- failed to read fd flags for preserved bubblewrap file descri
- root tool schema must be an object
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/7cf68cf5624027ad.
Report an issue: GitHub.