From 77f0cbfdd52e813dbbed661e5524e9cc3f160096 Mon Sep 17 00:00:00 2001 From: iceweasel-oai Date: Tue, 27 Oct 2026 16:54:20 +0000 Subject: [PATCH] Limit MXC volume expansion probes to symbolic links (#57515) ## What changed Use directory-entry file types when expanding volume-root grants, and resolve metadata only for symbolic links. Skip links whose targets cannot be resolved, while preserving grants for ordinary children and valid links. ## Testing Extend the volume-expansion test to cover dangling and self-referential links alongside an ordinary file, a valid symbolic link, and an explicit deny grant. GitOrigin-RevId: 8acb4072a1f5edd4351738b5780ac659fdf94f01 --- codex-rs/mxc-sandbox/src/policy.rs | 10 ++++------ codex-rs/mxc-sandbox/src/policy_tests.rs | 13 +++++++++++-- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/codex-rs/mxc-sandbox/src/policy.rs b/codex-rs/mxc-sandbox/src/policy.rs index 11ebd06cd6..c008d4fd59 100644 --- a/codex-rs/mxc-sandbox/src/policy.rs +++ b/codex-rs/mxc-sandbox/src/policy.rs @@ -17,8 +17,6 @@ use codex_windows_sandbox::resolve_windows_deny_read_paths; use mxc_sdk::mxc_common::cmdline::CommandLineContext; use mxc_sdk::mxc_common::cmdline::CommandLineError; use mxc_sdk::mxc_common::cmdline::cmdline_from_argv_for_context; -use mxc_sdk::mxc_common::filesystem_object::ExistingObjectComparison; -use mxc_sdk::mxc_common::filesystem_object::compare_existing_filesystem_objects; use mxc_sdk::mxc_common::models::BaseProcessUiConfig; use mxc_sdk::mxc_common::models::ContainerPolicy; use mxc_sdk::mxc_common::models::ExecutionRequest; @@ -373,10 +371,10 @@ fn expand_volume_roots( if child.to_str().is_none() { continue; } - // A self-comparison is MXC's public object-identity probe. - // Generated grants can be skipped; explicit paths go to BaseContainer. - if compare_existing_filesystem_objects(&child, &child) - != ExistingObjectComparison::Same + // Windows supplies the file type with directory entries. + // Only resolve links: broken targets prevent PSEC startup. + if entry.file_type().is_ok_and(|kind| kind.is_symlink()) + && std::fs::metadata(&child).is_err() { continue; } diff --git a/codex-rs/mxc-sandbox/src/policy_tests.rs b/codex-rs/mxc-sandbox/src/policy_tests.rs index bb2b1729cb..04e364baf0 100644 --- a/codex-rs/mxc-sandbox/src/policy_tests.rs +++ b/codex-rs/mxc-sandbox/src/policy_tests.rs @@ -324,11 +324,16 @@ fn volume_expansion_does_not_turn_read_only_child_writable() -> Result<()> { #[cfg(unix)] #[test] -fn volume_expansion_skips_uninspectable_children() -> Result<()> { +fn volume_expansion_skips_broken_links_and_preserves_other_grants() -> Result<()> { let temp = tempfile::tempdir()?; let root = canonical_root(&temp)?; let uninspectable = root.join("loop"); std::os::unix::fs::symlink(&uninspectable, &uninspectable)?; + std::os::unix::fs::symlink(root.join("missing"), root.join("dangling"))?; + let readable = root.join("readable"); + std::fs::write(&readable, "readable")?; + let alias = root.join("alias"); + std::os::unix::fs::symlink(&readable, &alias)?; let denied = root.join("secret"); std::fs::write(&denied, "secret")?; let fs = FileSystemSandboxPolicy::restricted(vec![ @@ -347,7 +352,11 @@ fn volume_expansion_skips_uninspectable_children() -> Result<()> { assert_eq!( (request.policy.readwrite_paths, request.policy.denied_paths), ( - vec![root.to_str().unwrap().to_owned()], + vec![ + root.to_str().unwrap().to_owned(), + alias.to_str().unwrap().to_owned(), + readable.to_str().unwrap().to_owned() + ], vec![denied.to_str().unwrap().to_owned()], ) );