mirror of
https://github.com/openai/codex.git
synced 2026-11-10 08:43:33 +00:00
Preserve target-native paths in command approvals (#42577)
## What changed - Pass the selected executor's `PathUri` through user command approval requests instead of converting the working directory to a host-native path. - Make native-path permission helpers explicitly local and require executor-aware permission transforms to receive a `FileSystemSandboxPolicyContext`. - Cover approved remote commands to verify that the approval request reports the selected remote working directory and execution resumes after approval. GitOrigin-RevId: 0aa3042f2d7594af6c7d0abf31d7f99cf67d5556
This commit is contained in:
1 parent
0650d6d1ca
commit
7a7c188682
30 files changed
+304
-368
No files matched your search
@@ -2383,7 +2383,7 @@ async fn default_permissions_profile_populates_runtime_sandbox_policy() -> std::
|
||||
!config
|
||||
.permissions
|
||||
.file_system_sandbox_policy()
|
||||
.can_write_path_with_cwd(&cwd.path().join(".git"), cwd.path())
|
||||
.can_write_local_path_with_cwd(&cwd.path().join(".git"), cwd.path())
|
||||
);
|
||||
assert_eq!(
|
||||
config.permissions.network_sandbox_policy(),
|
||||
@@ -2828,7 +2828,7 @@ async fn permission_profile_override_keeps_memories_root_out_of_legacy_projectio
|
||||
!config
|
||||
.permissions
|
||||
.file_system_sandbox_policy()
|
||||
.can_write_path_with_cwd(memories_root.as_path(), cwd.path())
|
||||
.can_write_local_path_with_cwd(memories_root.as_path(), cwd.path())
|
||||
);
|
||||
assert_eq!(
|
||||
&config.legacy_sandbox_policy(),
|
||||
@@ -3064,11 +3064,11 @@ async fn default_permissions_can_select_builtin_profile_without_permissions_tabl
|
||||
Some(BUILT_IN_PERMISSION_PROFILE_WORKSPACE)
|
||||
);
|
||||
assert!(
|
||||
policy.can_write_path_with_cwd(cwd.path(), cwd.path()),
|
||||
policy.can_write_local_path_with_cwd(cwd.path(), cwd.path()),
|
||||
"expected :workspace to allow writing the project root, policy: {policy:?}"
|
||||
);
|
||||
assert!(
|
||||
!policy.can_write_path_with_cwd(&cwd.path().join(".git"), cwd.path()),
|
||||
!policy.can_write_local_path_with_cwd(&cwd.path().join(".git"), cwd.path()),
|
||||
"expected :workspace to protect project metadata, policy: {policy:?}"
|
||||
);
|
||||
Ok(())
|
||||
@@ -3097,7 +3097,7 @@ async fn default_permissions_read_only_keeps_add_dir_read_only() -> std::io::Res
|
||||
|
||||
let policy = config.permissions.file_system_sandbox_policy();
|
||||
assert!(
|
||||
!policy.can_write_path_with_cwd(extra_root.as_path(), cwd.path()),
|
||||
!policy.can_write_local_path_with_cwd(extra_root.as_path(), cwd.path()),
|
||||
"expected :read-only to stay read-only for runtime workspace roots, policy: {policy:?}"
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -3186,15 +3186,15 @@ async fn workspace_profile_applies_rules_to_runtime_and_profile_workspace_roots(
|
||||
let policy = config.permissions.file_system_sandbox_policy();
|
||||
for root in [cwd_abs, runtime_root_abs, profile_root_abs.clone()] {
|
||||
assert!(
|
||||
policy.can_write_path_with_cwd(root.as_path(), cwd.as_path()),
|
||||
policy.can_write_local_path_with_cwd(root.as_path(), cwd.as_path()),
|
||||
"expected workspace root to be writable, policy: {policy:?}"
|
||||
);
|
||||
assert!(
|
||||
!policy.can_write_path_with_cwd(&root.join(".git"), cwd.as_path()),
|
||||
!policy.can_write_local_path_with_cwd(&root.join(".git"), cwd.as_path()),
|
||||
"expected .git carveout under {root:?}, policy: {policy:?}"
|
||||
);
|
||||
assert!(
|
||||
!policy.can_write_path_with_cwd(&root.join(".codex"), cwd.as_path()),
|
||||
!policy.can_write_local_path_with_cwd(&root.join(".codex"), cwd.as_path()),
|
||||
"expected .codex carveout under {root:?}, policy: {policy:?}"
|
||||
);
|
||||
}
|
||||
@@ -3293,11 +3293,11 @@ async fn default_permissions_profile_can_extend_builtin_workspace() -> std::io::
|
||||
|
||||
let policy = config.permissions.file_system_sandbox_policy();
|
||||
assert!(
|
||||
policy.can_write_path_with_cwd(cwd.path(), cwd.path()),
|
||||
policy.can_write_local_path_with_cwd(cwd.path(), cwd.path()),
|
||||
"expected profile extending :workspace to keep project-root writes, policy: {policy:?}"
|
||||
);
|
||||
assert!(
|
||||
!policy.can_write_path_with_cwd(&cwd.path().join(".git"), cwd.path()),
|
||||
!policy.can_write_local_path_with_cwd(&cwd.path().join(".git"), cwd.path()),
|
||||
"expected profile extending :workspace to keep metadata carveouts, policy: {policy:?}"
|
||||
);
|
||||
assert!(
|
||||
@@ -3388,11 +3388,11 @@ async fn default_permissions_profile_can_extend_builtin_read_only() -> std::io::
|
||||
|
||||
let policy = config.permissions.file_system_sandbox_policy();
|
||||
assert!(
|
||||
policy.can_read_path_with_cwd(cwd.path(), cwd.path()),
|
||||
policy.can_read_local_path_with_cwd(cwd.path(), cwd.path()),
|
||||
"expected profile extending :read-only to keep read access, policy: {policy:?}"
|
||||
);
|
||||
assert!(
|
||||
!policy.can_write_path_with_cwd(cwd.path(), cwd.path()),
|
||||
!policy.can_write_local_path_with_cwd(cwd.path(), cwd.path()),
|
||||
"expected profile extending :read-only to stay non-writable, policy: {policy:?}"
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -3448,16 +3448,16 @@ async fn empty_config_defaults_to_builtin_profile_for_trusted_project() -> std::
|
||||
);
|
||||
if cfg!(target_os = "windows") {
|
||||
assert!(
|
||||
!policy.can_write_path_with_cwd(cwd.path(), cwd.path()),
|
||||
!policy.can_write_local_path_with_cwd(cwd.path(), cwd.path()),
|
||||
"expected trusted project fallback to stay read-only without Windows sandbox support, policy: {policy:?}"
|
||||
);
|
||||
} else {
|
||||
assert!(
|
||||
policy.can_write_path_with_cwd(cwd.path(), cwd.path()),
|
||||
policy.can_write_local_path_with_cwd(cwd.path(), cwd.path()),
|
||||
"expected trusted project fallback to use :workspace, policy: {policy:?}"
|
||||
);
|
||||
assert!(
|
||||
!policy.can_write_path_with_cwd(&cwd.path().join(".codex"), cwd.path()),
|
||||
!policy.can_write_local_path_with_cwd(&cwd.path().join(".codex"), cwd.path()),
|
||||
"expected :workspace metadata carveouts, policy: {policy:?}"
|
||||
);
|
||||
}
|
||||
@@ -3502,21 +3502,21 @@ async fn empty_config_defaults_to_builtin_profile_for_untrusted_project() -> std
|
||||
})
|
||||
);
|
||||
assert!(
|
||||
policy.can_read_path_with_cwd(cwd.path(), cwd.path()),
|
||||
policy.can_read_local_path_with_cwd(cwd.path(), cwd.path()),
|
||||
"expected untrusted project fallback to allow reads, policy: {policy:?}"
|
||||
);
|
||||
if cfg!(target_os = "windows") {
|
||||
assert!(
|
||||
!policy.can_write_path_with_cwd(cwd.path(), cwd.path()),
|
||||
!policy.can_write_local_path_with_cwd(cwd.path(), cwd.path()),
|
||||
"expected untrusted project fallback to stay read-only without Windows sandbox support, policy: {policy:?}"
|
||||
);
|
||||
} else {
|
||||
assert!(
|
||||
policy.can_write_path_with_cwd(cwd.path(), cwd.path()),
|
||||
policy.can_write_local_path_with_cwd(cwd.path(), cwd.path()),
|
||||
"expected untrusted project fallback to use :workspace, policy: {policy:?}"
|
||||
);
|
||||
assert!(
|
||||
!policy.can_write_path_with_cwd(&cwd.path().join(".codex"), cwd.path()),
|
||||
!policy.can_write_local_path_with_cwd(&cwd.path().join(".codex"), cwd.path()),
|
||||
"expected :workspace metadata carveouts, policy: {policy:?}"
|
||||
);
|
||||
}
|
||||
@@ -3562,7 +3562,7 @@ async fn implicit_builtin_workspace_profile_preserves_sandbox_workspace_write_se
|
||||
|
||||
let policy = config.permissions.file_system_sandbox_policy();
|
||||
assert!(
|
||||
policy.can_write_path_with_cwd(extra_root.as_path(), cwd.path()),
|
||||
policy.can_write_local_path_with_cwd(extra_root.as_path(), cwd.path()),
|
||||
"expected implicit :workspace to preserve sandbox_workspace_write.writable_roots, policy: {policy:?}"
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -3629,12 +3629,12 @@ async fn implicit_builtin_workspace_profile_preserves_add_dir_metadata_carveouts
|
||||
let policy = config.permissions.file_system_sandbox_policy();
|
||||
let extra_root = extra_root.path().abs();
|
||||
assert!(
|
||||
policy.can_write_path_with_cwd(extra_root.as_path(), cwd.path()),
|
||||
policy.can_write_local_path_with_cwd(extra_root.as_path(), cwd.path()),
|
||||
"expected implicit :workspace to preserve additional writable roots, policy: {policy:?}"
|
||||
);
|
||||
for subpath in [".git", ".agents", ".codex"] {
|
||||
assert!(
|
||||
!policy.can_write_path_with_cwd(&extra_root.join(subpath), cwd.path()),
|
||||
!policy.can_write_local_path_with_cwd(&extra_root.join(subpath), cwd.path()),
|
||||
"expected implicit :workspace to preserve legacy metadata carveout for {subpath}, \
|
||||
policy: {policy:?}"
|
||||
);
|
||||
@@ -3660,11 +3660,11 @@ async fn empty_config_defaults_to_builtin_read_only_without_trust_decision() ->
|
||||
|
||||
let policy = config.permissions.file_system_sandbox_policy();
|
||||
assert!(
|
||||
policy.can_read_path_with_cwd(cwd.path(), cwd.path()),
|
||||
policy.can_read_local_path_with_cwd(cwd.path(), cwd.path()),
|
||||
"expected :read-only to allow reads, policy: {policy:?}"
|
||||
);
|
||||
assert!(
|
||||
!policy.can_write_path_with_cwd(cwd.path(), cwd.path()),
|
||||
!policy.can_write_local_path_with_cwd(cwd.path(), cwd.path()),
|
||||
"expected :read-only to deny writes, policy: {policy:?}"
|
||||
);
|
||||
Ok(())
|
||||
@@ -3842,7 +3842,7 @@ async fn permissions_profiles_allow_direct_write_roots_outside_workspace_root()
|
||||
config
|
||||
.permissions
|
||||
.file_system_sandbox_policy()
|
||||
.can_write_path_with_cwd(external_write_path.as_path(), cwd.path())
|
||||
.can_write_local_path_with_cwd(external_write_path.as_path(), cwd.path())
|
||||
);
|
||||
assert_eq!(
|
||||
&config.legacy_sandbox_policy(),
|
||||
@@ -6035,8 +6035,12 @@ async fn memory_tool_makes_memories_root_readable_without_creating_or_widening_w
|
||||
memories_root.display()
|
||||
);
|
||||
let file_system_policy = config.permissions.file_system_sandbox_policy();
|
||||
assert!(file_system_policy.can_read_path_with_cwd(memories_root_abs.as_path(), cwd.path()));
|
||||
assert!(!file_system_policy.can_write_path_with_cwd(memories_root_abs.as_path(), cwd.path()));
|
||||
assert!(
|
||||
file_system_policy.can_read_local_path_with_cwd(memories_root_abs.as_path(), cwd.path())
|
||||
);
|
||||
assert!(
|
||||
!file_system_policy.can_write_local_path_with_cwd(memories_root_abs.as_path(), cwd.path())
|
||||
);
|
||||
|
||||
if cfg!(target_os = "windows") {
|
||||
match &config.legacy_sandbox_policy() {
|
||||
@@ -10975,7 +10979,7 @@ async fn permission_profile_override_preserves_split_write_roots() -> std::io::R
|
||||
config
|
||||
.permissions
|
||||
.file_system_sandbox_policy()
|
||||
.can_write_path_with_cwd(outside_root.as_path(), config.cwd.as_path())
|
||||
.can_write_local_path_with_cwd(outside_root.as_path(), config.cwd.as_path())
|
||||
);
|
||||
assert!(matches!(
|
||||
&config.legacy_sandbox_policy(),
|
||||
|
||||
@@ -4091,17 +4091,14 @@ impl Config {
|
||||
}) = filesystem_requirements.as_ref()
|
||||
&& let Some(managed_file_system_policy) = managed_deny_read_policy.as_ref()
|
||||
{
|
||||
let _initial_matcher =
|
||||
ReadDenyMatcher::try_new(managed_file_system_policy, resolved_cwd.as_path())
|
||||
let managed_deny_matcher =
|
||||
ReadDenyMatcher::try_new_for_local_paths(managed_file_system_policy, resolved_cwd.as_path())
|
||||
.map_err(std::io::Error::other)?;
|
||||
let managed_file_system_policy = Arc::clone(managed_file_system_policy);
|
||||
let permission_cwd = resolved_cwd.clone();
|
||||
let requirement_source = requirement_source.clone();
|
||||
constrained_permission_profile
|
||||
.value
|
||||
.add_validator(move |permission_profile| {
|
||||
let managed_deny_matcher =
|
||||
ReadDenyMatcher::new(&managed_file_system_policy, permission_cwd.as_path());
|
||||
let file_system_policy = permission_profile.file_system_sandbox_policy();
|
||||
let missing_required_deny = managed_file_system_policy
|
||||
.entries
|
||||
@@ -4118,7 +4115,7 @@ impl Config {
|
||||
let path = path.to_abs_path().ok()?;
|
||||
managed_deny_matcher
|
||||
.as_ref()
|
||||
.is_some_and(|matcher| matcher.is_read_denied(path.as_path()))
|
||||
.is_some_and(|matcher| matcher.is_local_path_read_denied(path.as_path()))
|
||||
.then_some(path)
|
||||
});
|
||||
if missing_required_deny || violating_root.is_some() {
|
||||
|
||||
@@ -96,15 +96,15 @@ async fn restricted_read_implicitly_allows_helper_executables() -> std::io::Resu
|
||||
let policy = config.permissions.file_system_sandbox_policy();
|
||||
|
||||
assert!(
|
||||
policy.can_read_path_with_cwd(expected_zsh.as_path(), &cwd),
|
||||
policy.can_read_local_path_with_cwd(expected_zsh.as_path(), &cwd),
|
||||
"expected zsh helper path to be readable, policy: {policy:?}"
|
||||
);
|
||||
assert!(
|
||||
policy.can_read_path_with_cwd(expected_allowed_arg0_dir.as_path(), &cwd),
|
||||
policy.can_read_local_path_with_cwd(expected_allowed_arg0_dir.as_path(), &cwd),
|
||||
"expected active arg0 helper dir to be readable, policy: {policy:?}"
|
||||
);
|
||||
assert!(
|
||||
!policy.can_read_path_with_cwd(expected_sibling_arg0_dir.as_path(), &cwd),
|
||||
!policy.can_read_local_path_with_cwd(expected_sibling_arg0_dir.as_path(), &cwd),
|
||||
"expected sibling arg0 helper dir to remain unreadable, policy: {policy:?}"
|
||||
);
|
||||
|
||||
@@ -493,7 +493,7 @@ docs = "read"
|
||||
let (read_deny_policy, _) =
|
||||
compile_permission_profile(&permissions, "read_deny", &mut startup_warnings)?;
|
||||
assert_eq!(
|
||||
read_deny_policy.resolve_access_with_cwd(cwd.path(), cwd.path()),
|
||||
read_deny_policy.resolve_access_for_local_path_with_cwd(cwd.path(), cwd.path()),
|
||||
FileSystemAccessMode::Deny
|
||||
);
|
||||
|
||||
@@ -501,7 +501,7 @@ docs = "read"
|
||||
compile_permission_profile(&permissions, "write_deny", &mut startup_warnings)?;
|
||||
assert!(!write_deny_policy.has_full_disk_write_access());
|
||||
assert_eq!(
|
||||
write_deny_policy.resolve_access_with_cwd(cwd.path(), cwd.path()),
|
||||
write_deny_policy.resolve_access_for_local_path_with_cwd(cwd.path(), cwd.path()),
|
||||
FileSystemAccessMode::Deny
|
||||
);
|
||||
|
||||
@@ -509,7 +509,7 @@ docs = "read"
|
||||
compile_permission_profile(&permissions, "write_read", &mut startup_warnings)?;
|
||||
assert!(!write_read_policy.has_full_disk_write_access());
|
||||
assert_eq!(
|
||||
write_read_policy.resolve_access_with_cwd(&docs, cwd.path()),
|
||||
write_read_policy.resolve_access_for_local_path_with_cwd(&docs, cwd.path()),
|
||||
FileSystemAccessMode::Read
|
||||
);
|
||||
|
||||
|
||||
Reference in new issue
Block a user