chore: trim stale deny_read policy churn

This commit is contained in:
viyatb-oai
2026-03-08 01:03:37 -08:00
parent 4778497f3d
commit dcbbaeb993
29 changed files with 55 additions and 98 deletions
@@ -1378,7 +1378,6 @@ async fn turn_start_updates_sandbox_and_cwd_between_turns_v2() -> Result<()> {
sandbox_policy: Some(codex_app_server_protocol::SandboxPolicy::WorkspaceWrite {
writable_roots: vec![first_cwd.try_into()?],
read_only_access: codex_app_server_protocol::ReadOnlyAccess::FullAccess,
deny_read_paths: vec![],
network_access: false,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
@@ -527,7 +527,6 @@ async fn turn_start_shell_zsh_fork_subcommand_decline_marks_parent_declined_v2()
sandbox_policy: Some(codex_app_server_protocol::SandboxPolicy::WorkspaceWrite {
writable_roots: vec![workspace.clone().try_into()?],
read_only_access: codex_app_server_protocol::ReadOnlyAccess::FullAccess,
deny_read_paths: vec![],
network_access: false,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
@@ -1110,7 +1110,6 @@ mod tests {
.can_set(&SandboxPolicy::WorkspaceWrite {
writable_roots: vec![AbsolutePathBuf::from_absolute_path(root)?],
read_only_access: Default::default(),
deny_read_paths: vec![],
network_access: false,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
@@ -1133,7 +1132,6 @@ mod tests {
.sandbox_policy
.can_set(&SandboxPolicy::ExternalSandbox {
network_access: NetworkAccess::Restricted,
deny_read_paths: vec![],
}),
Err(ConstraintError::InvalidValue {
field_name: "sandbox_mode",
-1
View File
@@ -431,7 +431,6 @@ allowed_sandbox_modes = ["read-only"]
.can_set(&SandboxPolicy::WorkspaceWrite {
writable_roots: Vec::new(),
read_only_access: Default::default(),
deny_read_patterns: vec![],
network_access: false,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
+7 -4
View File
@@ -2105,11 +2105,13 @@ prefix_rule(pattern=["git"], decision="prompt")
let policy = Arc::new(parser.build());
let command = vec!["cat".to_string(), "~/.gitconfig".to_string()];
let mut sandbox_policy = SandboxPolicy::new_workspace_write_policy();
let sandbox_policy = SandboxPolicy::new_workspace_write_policy();
let deny_path = AbsolutePathBuf::try_from("/tmp/secret-config").expect("absolute path");
sandbox_policy.append_deny_read_patterns(&[crate::protocol::DenyReadPattern::from(
deny_path.to_string_lossy().into_owned(),
)]);
let file_system_sandbox_policy =
FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry {
path: FileSystemPath::Path { path: deny_path },
access: FileSystemAccessMode::None,
}]);
let manager = ExecPolicyManager::new(policy);
let requirement = manager
@@ -2117,6 +2119,7 @@ prefix_rule(pattern=["git"], decision="prompt")
command: &command,
approval_policy: AskForApproval::OnRequest,
sandbox_policy: &sandbox_policy,
file_system_sandbox_policy: &file_system_sandbox_policy,
sandbox_permissions: SandboxPermissions::UseDefault,
prefix_rule: None,
})
-5
View File
@@ -225,7 +225,6 @@ mod tests {
let policy_workspace_only = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![],
read_only_access: Default::default(),
deny_read_patterns: vec![],
network_access: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
@@ -248,7 +247,6 @@ mod tests {
let policy_with_parent = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![AbsolutePathBuf::try_from(parent).unwrap()],
read_only_access: Default::default(),
deny_read_patterns: vec![],
network_access: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
@@ -268,7 +266,6 @@ mod tests {
let policy = SandboxPolicy::ExternalSandbox {
network_access: codex_protocol::protocol::NetworkAccess::Enabled,
deny_read_patterns: vec![],
};
assert_eq!(
@@ -297,7 +294,6 @@ mod tests {
let policy_workspace_only = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![],
read_only_access: Default::default(),
deny_read_patterns: vec![],
network_access: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
@@ -341,7 +337,6 @@ mod tests {
let policy_workspace_only = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![],
read_only_access: Default::default(),
deny_read_patterns: vec![],
network_access: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
-1
View File
@@ -52,7 +52,6 @@ mod tests {
let actual = sandbox_tag(
&SandboxPolicy::ExternalSandbox {
network_access: NetworkAccess::Enabled,
deny_read_patterns: vec![],
},
WindowsSandboxLevel::Disabled,
true,
+1 -1
View File
@@ -447,7 +447,7 @@ fn seatbelt_regex_for_deny_read_pattern(pattern: &str) -> Option<String> {
saw_glob = true;
let mut class = String::new();
let mut closed = false;
while let Some(class_ch) = chars.next() {
for class_ch in chars.by_ref() {
if class_ch == ']' {
closed = true;
break;
+21 -15
View File
@@ -300,9 +300,10 @@ impl From<&FileType> for DirEntryKind {
#[cfg(test)]
mod tests {
use super::*;
use crate::protocol::DenyReadPattern;
use crate::protocol::ReadOnlyAccess;
use crate::protocol::SandboxPolicy;
use codex_protocol::permissions::FileSystemAccessMode;
use codex_protocol::permissions::FileSystemPath;
use codex_protocol::permissions::FileSystemSandboxEntry;
use codex_protocol::permissions::FileSystemSandboxPolicy;
use pretty_assertions::assert_eq;
use tempfile::tempdir;
@@ -566,20 +567,25 @@ mod tests {
.await
.expect("write denied top-level file");
let policy = SandboxPolicy::ReadOnly {
access: ReadOnlyAccess::FullAccess,
deny_read_patterns: vec![
DenyReadPattern::from(denied_dir.to_string_lossy().into_owned()),
DenyReadPattern::from(
dir_path
let policy = FileSystemSandboxPolicy::restricted(vec![
FileSystemSandboxEntry {
path: FileSystemPath::Path {
path: denied_dir.try_into().expect("absolute denied dir"),
},
access: FileSystemAccessMode::None,
},
FileSystemSandboxEntry {
path: FileSystemPath::Path {
path: dir_path
.join("top_secret.txt")
.to_string_lossy()
.into_owned(),
),
],
};
.try_into()
.expect("absolute denied file"),
},
access: FileSystemAccessMode::None,
},
]);
let entries = list_dir_slice_with_policy(dir_path, 1, 20, 3, Some(&policy))
let entries = list_dir_slice_with_policy(dir_path, 1, 20, 3, Some((&policy, dir_path)))
.await
.expect("list directory");
+12 -10
View File
@@ -167,18 +167,20 @@ fn reject_explicit_escalation_if_deny_read_present(
mod tests {
use super::reject_explicit_escalation_if_deny_read_present;
use crate::function_tool::FunctionCallError;
use crate::protocol::DenyReadPattern;
use crate::protocol::SandboxPolicy;
use crate::sandboxing::SandboxPermissions;
use codex_protocol::permissions::FileSystemAccessMode;
use codex_protocol::permissions::FileSystemPath;
use codex_protocol::permissions::FileSystemSandboxEntry;
use codex_protocol::permissions::FileSystemSandboxPolicy;
use codex_utils_absolute_path::AbsolutePathBuf;
#[test]
fn explicit_escalation_is_rejected_when_deny_read_paths_exist() {
let mut policy = SandboxPolicy::new_workspace_write_policy();
let path = AbsolutePathBuf::try_from("/tmp/deny-read-test").expect("absolute path");
policy.append_deny_read_patterns(&[DenyReadPattern::from(
path.to_string_lossy().into_owned(),
)]);
let policy = FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry {
path: FileSystemPath::Path { path },
access: FileSystemAccessMode::None,
}]);
let result = reject_explicit_escalation_if_deny_read_present(
SandboxPermissions::RequireEscalated,
@@ -193,11 +195,11 @@ mod tests {
#[test]
fn non_escalated_command_is_allowed_when_deny_read_paths_exist() {
let mut policy = SandboxPolicy::new_workspace_write_policy();
let path = AbsolutePathBuf::try_from("/tmp/deny-read-test").expect("absolute path");
policy.append_deny_read_patterns(&[DenyReadPattern::from(
path.to_string_lossy().into_owned(),
)]);
let policy = FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry {
path: FileSystemPath::Path { path },
access: FileSystemAccessMode::None,
}]);
let result = reject_explicit_escalation_if_deny_read_present(
SandboxPermissions::UseDefault,
@@ -227,7 +227,6 @@ fn shell_request_escalation_execution_is_explicit() {
network_access: false,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
deny_read_patterns: vec![],
};
let file_system_sandbox_policy = FileSystemSandboxPolicy::restricted(vec![
FileSystemSandboxEntry {
-1
View File
@@ -370,7 +370,6 @@ mod tests {
AskForApproval::OnRequest,
&SandboxPolicy::ExternalSandbox {
network_access: NetworkAccess::Restricted,
deny_read_patterns: vec![],
},
),
ExecApprovalRequirement::Skip {
-1
View File
@@ -47,7 +47,6 @@ pub fn restrictive_workspace_write_policy() -> SandboxPolicy {
network_access: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
deny_read_patterns: Vec::new(),
}
}
@@ -581,7 +581,6 @@ async fn apply_patch_cli_rejects_path_traversal_outside_workspace(
let sandbox_policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![],
read_only_access: Default::default(),
deny_read_patterns: vec![],
network_access: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
@@ -639,7 +638,6 @@ async fn apply_patch_cli_rejects_move_path_traversal_outside_workspace(
let sandbox_policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![],
read_only_access: Default::default(),
deny_read_patterns: vec![],
network_access: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
-3
View File
@@ -683,7 +683,6 @@ fn scenarios() -> Vec<ScenarioSpec> {
let workspace_write = |network_access| SandboxPolicy::WorkspaceWrite {
writable_roots: vec![],
read_only_access: Default::default(),
deny_read_patterns: vec![],
network_access,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
@@ -1708,7 +1707,6 @@ async fn approving_apply_patch_for_session_skips_future_prompts_for_same_file()
let sandbox_policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![],
read_only_access: Default::default(),
deny_read_patterns: vec![],
network_access: false,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
@@ -2254,7 +2252,6 @@ allow_local_binding = true
network_access: true,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
deny_read_patterns: vec![],
};
let sandbox_policy_for_config = sandbox_policy.clone();
let mut builder = test_codex().with_home(home).with_config(move |config| {
@@ -461,7 +461,6 @@ async fn permissions_message_includes_writable_roots() -> Result<()> {
let sandbox_policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![writable_root],
read_only_access: Default::default(),
deny_read_patterns: vec![],
network_access: false,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
@@ -415,7 +415,6 @@ async fn overrides_turn_context_but_keeps_cached_prefix_and_key_constant() -> an
let new_policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![writable.path().try_into().unwrap()],
read_only_access: Default::default(),
deny_read_patterns: vec![],
network_access: true,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
@@ -685,7 +684,6 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res
let new_policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![AbsolutePathBuf::try_from(writable.path()).unwrap()],
read_only_access: Default::default(),
deny_read_patterns: vec![],
network_access: true,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
@@ -184,7 +184,6 @@ fn workspace_write_excluding_tmp() -> SandboxPolicy {
network_access: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
deny_read_patterns: vec![],
}
}
-2
View File
@@ -78,7 +78,6 @@ async fn if_parent_of_repo_is_writable_then_dot_git_folder_is_writable() {
let policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![test_scenario.repo_parent.as_path().try_into().unwrap()],
read_only_access: Default::default(),
deny_read_patterns: vec![],
network_access: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
@@ -106,7 +105,6 @@ async fn if_git_repo_is_writable_root_then_dot_git_folder_is_read_only() {
let policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![test_scenario.repo_root.as_path().try_into().unwrap()],
read_only_access: Default::default(),
deny_read_patterns: vec![],
network_access: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
-2
View File
@@ -135,7 +135,6 @@ async fn python_multiprocessing_lock_works_under_sandbox() {
let policy = SandboxPolicy::WorkspaceWrite {
writable_roots,
read_only_access: Default::default(),
deny_read_paths: vec![],
network_access: false,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
@@ -250,7 +249,6 @@ async fn sandbox_distinguishes_command_and_policy_cwds() {
let policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![],
read_only_access: Default::default(),
deny_read_paths: vec![],
network_access: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
-1
View File
@@ -1661,7 +1661,6 @@ mod tests {
let policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![],
read_only_access: Default::default(),
deny_read_patterns: vec![],
network_access: true,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
-1
View File
@@ -57,7 +57,6 @@ mod tests {
fn returns_none_for_external_sandbox() {
let sandbox = SandboxPolicy::ExternalSandbox {
network_access: NetworkAccess::Enabled,
deny_read_paths: vec![],
};
let dirs = vec![PathBuf::from("/tmp/example")];
assert_eq!(add_dir_warning_message(&dirs, &sandbox), None);
-1
View File
@@ -7232,7 +7232,6 @@ async fn preset_matching_requires_exact_workspace_write_settings() {
let current_sandbox = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![AbsolutePathBuf::try_from("C:\\extra").unwrap()],
read_only_access: Default::default(),
deny_read_paths: Vec::new(),
network_access: false,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
+14 -27
View File
@@ -197,29 +197,20 @@ impl StatusHistoryCell {
.find(|(k, _)| *k == "approval")
.map(|(_, v)| v.clone())
.unwrap_or_else(|| "<unknown>".to_string());
let sandbox = if config
.permissions
.sandbox_policy
.get()
.behaves_like_danger_full_access()
{
"danger-full-access".to_string()
} else {
match config.permissions.sandbox_policy.get() {
SandboxPolicy::ReadOnly { .. } => "read-only".to_string(),
SandboxPolicy::WorkspaceWrite {
network_access: true,
..
} => "workspace-write with network access".to_string(),
SandboxPolicy::WorkspaceWrite { .. } => "workspace-write".to_string(),
SandboxPolicy::ExternalSandbox { network_access, .. } => {
if matches!(network_access, NetworkAccess::Enabled) {
"external-sandbox (network access enabled)".to_string()
} else {
"external-sandbox".to_string()
}
let sandbox = match config.permissions.sandbox_policy.get() {
SandboxPolicy::DangerFullAccess => "danger-full-access".to_string(),
SandboxPolicy::ReadOnly { .. } => "read-only".to_string(),
SandboxPolicy::WorkspaceWrite {
network_access: true,
..
} => "workspace-write with network access".to_string(),
SandboxPolicy::WorkspaceWrite { .. } => "workspace-write".to_string(),
SandboxPolicy::ExternalSandbox { network_access } => {
if matches!(network_access, NetworkAccess::Enabled) {
"external-sandbox (network access enabled)".to_string()
} else {
"external-sandbox".to_string()
}
SandboxPolicy::DangerFullAccess => "danger-full-access".to_string(),
}
};
let permissions = if config.permissions.approval_policy.value() == AskForApproval::OnRequest
@@ -228,11 +219,7 @@ impl StatusHistoryCell {
{
"Default".to_string()
} else if config.permissions.approval_policy.value() == AskForApproval::Never
&& config
.permissions
.sandbox_policy
.get()
.behaves_like_danger_full_access()
&& *config.permissions.sandbox_policy.get() == SandboxPolicy::DangerFullAccess
{
"Full Access".to_string()
} else {
-2
View File
@@ -103,7 +103,6 @@ async fn status_snapshot_includes_reasoning_details() {
.set(SandboxPolicy::WorkspaceWrite {
writable_roots: Vec::new(),
read_only_access: Default::default(),
deny_read_paths: Vec::new(),
network_access: false,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
@@ -189,7 +188,6 @@ async fn status_permissions_non_default_workspace_write_is_custom() {
.set(SandboxPolicy::WorkspaceWrite {
writable_roots: Vec::new(),
read_only_access: Default::default(),
deny_read_paths: Vec::new(),
network_access: true,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
-6
View File
@@ -110,7 +110,6 @@ mod tests {
let policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![AbsolutePathBuf::try_from(extra_root.as_path()).unwrap()],
deny_read_paths: vec![],
read_only_access: Default::default(),
network_access: false,
exclude_tmpdir_env_var: false,
@@ -138,7 +137,6 @@ mod tests {
let policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![],
deny_read_paths: vec![],
read_only_access: Default::default(),
network_access: false,
exclude_tmpdir_env_var: true,
@@ -167,7 +165,6 @@ mod tests {
let policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![],
deny_read_paths: vec![],
read_only_access: Default::default(),
network_access: false,
exclude_tmpdir_env_var: true,
@@ -196,7 +193,6 @@ mod tests {
let policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![],
deny_read_paths: vec![],
read_only_access: Default::default(),
network_access: false,
exclude_tmpdir_env_var: true,
@@ -226,7 +222,6 @@ mod tests {
let policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![],
deny_read_paths: vec![],
read_only_access: Default::default(),
network_access: false,
exclude_tmpdir_env_var: true,
@@ -256,7 +251,6 @@ mod tests {
let policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![],
deny_read_paths: vec![],
read_only_access: Default::default(),
network_access: false,
exclude_tmpdir_env_var: true,
@@ -486,7 +486,6 @@ mod windows_impl {
fn workspace_policy(network_access: bool) -> SandboxPolicy {
SandboxPolicy::WorkspaceWrite {
writable_roots: Vec::new(),
deny_read_paths: Vec::new(),
read_only_access: Default::default(),
network_access,
exclude_tmpdir_env_var: false,
-1
View File
@@ -575,7 +575,6 @@ mod windows_impl {
fn workspace_policy(network_access: bool) -> SandboxPolicy {
SandboxPolicy::WorkspaceWrite {
writable_roots: Vec::new(),
deny_read_paths: Vec::new(),
read_only_access: Default::default(),
network_access,
exclude_tmpdir_env_var: false,
@@ -41,7 +41,6 @@ mod tests {
let payload = serde_json::to_string(
&codex_protocol::protocol::SandboxPolicy::ExternalSandbox {
network_access: codex_protocol::protocol::NetworkAccess::Enabled,
deny_read_paths: vec![],
},
)
.unwrap();