From 685883a32161ab4989192cbb4cd054e782d69e6f Mon Sep 17 00:00:00 2001 From: viyatb-oai Date: Mon, 2 Mar 2026 15:33:33 -0800 Subject: [PATCH] fix(linux-sandbox): mask missing deny_read paths --- codex-rs/linux-sandbox/src/bwrap.rs | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/codex-rs/linux-sandbox/src/bwrap.rs b/codex-rs/linux-sandbox/src/bwrap.rs index 8f400d4781..669c601a58 100644 --- a/codex-rs/linux-sandbox/src/bwrap.rs +++ b/codex-rs/linux-sandbox/src/bwrap.rs @@ -334,9 +334,6 @@ fn apply_deny_read_overlays( { continue; } - if !denied_path.exists() { - continue; - } if !full_read_access { let overlaps_visible_mounts = readable_roots @@ -350,6 +347,8 @@ fn apply_deny_read_overlays( } } + // Default missing paths to a file-style mask so the deny rule still + // blocks the exact path if it appears later during the sandbox run. let is_dir = std::fs::metadata(&denied_path) .map(|metadata| metadata.is_dir()) .unwrap_or(false); @@ -748,4 +747,25 @@ mod tests { .any(|window| window == ["--ro-bind", "/dev/null", denied_file_str.as_str()]) ); } + + #[test] + fn deny_read_overlays_mask_missing_paths() { + let temp_dir = TempDir::new().expect("temp dir"); + let denied_file = temp_dir.path().join("secret.txt"); + + let policy = SandboxPolicy::ReadOnly { + access: ReadOnlyAccess::FullAccess, + deny_read_paths: vec![ + AbsolutePathBuf::try_from(denied_file.as_path()).expect("absolute file"), + ], + }; + + let args = create_filesystem_args(&policy, temp_dir.path()).expect("filesystem args"); + let denied_file_str = path_to_string(&denied_file); + + assert!( + args.windows(3) + .any(|window| window == ["--ro-bind", "/dev/null", denied_file_str.as_str()]) + ); + } }