mirror of
https://github.com/openai/codex.git
synced 2026-11-13 22:47:20 +00:00
Skip missing paths in filesystem sandbox entries (#34598)
## Why Default read-only protections for project metadata should apply when paths such as `.git`, `.agents`, and `.codex` exist, without causing sandbox setup to materialize missing paths as ACL targets. ## What changed - Add an optional `missing_path_behavior` to filesystem sandbox entries and mark default project-metadata protections with `skip`. - Preserve the behavior through permission transforms and exec/MCP protocol serialization while keeping existing path wire variants stable. - Ignore skip-missing entries when projecting configuration or Windows sandbox overrides, while retaining explicit metadata carveouts. ## Testing - Cover protocol round trips for path and special-path entries. - Verify default metadata protections and Windows explicit carveout handling. GitOrigin-RevId: 6df13dadacdd131c44aab9f15a967c81051355c1
This commit is contained in:
1 parent
ee71c4a90f
commit
87f71e35b8
63 files changed
+825
-132
No files matched your search
@@ -2037,18 +2037,21 @@ async fn default_permissions_profile_populates_runtime_sandbox_policy() -> std::
|
||||
value: FileSystemSpecialPath::Minimal,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: cwd_root.clone(),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: cwd_root.join("docs"),
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]),
|
||||
);
|
||||
@@ -2295,12 +2298,14 @@ async fn permission_profile_override_keeps_memories_root_out_of_legacy_projectio
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::project_roots(/*subpath*/ None),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]),
|
||||
NetworkSandboxPolicy::Restricted,
|
||||
@@ -2461,6 +2466,7 @@ async fn workspace_root_glob_none_compiles_to_filesystem_pattern_entry() -> std:
|
||||
pattern: expected_pattern,
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -2800,6 +2806,7 @@ async fn default_permissions_profile_can_extend_builtin_workspace() -> std::io::
|
||||
value: FileSystemSpecialPath::SlashTmp,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
}
|
||||
)),
|
||||
"expected profile extending :workspace to keep inherited :slash_tmp writes, policy: {policy:?}"
|
||||
@@ -2812,6 +2819,7 @@ async fn default_permissions_profile_can_extend_builtin_workspace() -> std::io::
|
||||
value: FileSystemSpecialPath::Tmpdir,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
}
|
||||
)),
|
||||
"expected child :tmpdir read entry to replace the inherited write entry, policy: {policy:?}"
|
||||
@@ -2824,6 +2832,7 @@ async fn default_permissions_profile_can_extend_builtin_workspace() -> std::io::
|
||||
value: FileSystemSpecialPath::Tmpdir,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
}
|
||||
)),
|
||||
"expected inherited :tmpdir write entry to be removed, policy: {policy:?}"
|
||||
@@ -3446,6 +3455,7 @@ async fn permissions_profiles_allow_unknown_special_paths() -> std::io::Result<(
|
||||
),
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
}]),
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -3492,6 +3502,7 @@ async fn permissions_profiles_allow_unknown_special_paths_with_nested_entries()
|
||||
value: FileSystemSpecialPath::unknown(":future_special_path", Some("docs".into())),
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
}]),
|
||||
);
|
||||
assert!(
|
||||
@@ -4247,6 +4258,7 @@ exclude_slash_tmp = true
|
||||
.contains(&FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path { path: cwd.abs() },
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
})
|
||||
);
|
||||
assert!(
|
||||
@@ -4257,6 +4269,7 @@ exclude_slash_tmp = true
|
||||
path: extra_root.clone(),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
})
|
||||
);
|
||||
for subpath in [".git", ".agents", ".codex"] {
|
||||
@@ -4271,6 +4284,9 @@ exclude_slash_tmp = true
|
||||
),
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: Some(
|
||||
codex_protocol::permissions::FileSystemSandboxEntryMissingPathBehavior::Skip,
|
||||
),
|
||||
}),
|
||||
"case `{name}` should materialize `{subpath}` for the runtime workspace \
|
||||
root"
|
||||
@@ -9993,12 +10009,14 @@ async fn permission_profile_override_preserves_split_write_roots() -> std::io::R
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: outside_root.clone(),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions_with_enforcement(
|
||||
|
||||
@@ -2410,6 +2410,7 @@ fn apply_managed_filesystem_constraints(
|
||||
pattern: deny_read.as_str().to_string(),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
}
|
||||
} else {
|
||||
let Ok(path) = AbsolutePathBuf::try_from(deny_read.as_str()) else {
|
||||
@@ -2418,6 +2419,7 @@ fn apply_managed_filesystem_constraints(
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Path { path },
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
}
|
||||
};
|
||||
if !file_system_sandbox_policy
|
||||
|
||||
@@ -236,6 +236,10 @@ fn insert_filesystem_permission_toml(
|
||||
entries: &mut BTreeMap<String, FilesystemPermissionToml>,
|
||||
entry: FileSystemSandboxEntry,
|
||||
) {
|
||||
if entry.skips_missing_path() {
|
||||
return;
|
||||
}
|
||||
|
||||
match entry.path {
|
||||
FileSystemPath::Path { path } => {
|
||||
entries.insert(
|
||||
@@ -526,6 +530,7 @@ fn compile_filesystem_permission(
|
||||
entries.push(FileSystemSandboxEntry {
|
||||
path: compile_filesystem_access_path(path, *access, startup_warnings)?,
|
||||
access: *access,
|
||||
missing_path_behavior: None,
|
||||
});
|
||||
}
|
||||
FilesystemPermissionToml::Scoped(scoped_entries) => {
|
||||
@@ -544,6 +549,7 @@ fn compile_filesystem_permission(
|
||||
pattern: compile_scoped_filesystem_pattern(path, subpath, *access)?,
|
||||
},
|
||||
access: *access,
|
||||
missing_path_behavior: None,
|
||||
};
|
||||
entries.push(entry);
|
||||
} else {
|
||||
@@ -551,6 +557,7 @@ fn compile_filesystem_permission(
|
||||
entries.push(FileSystemSandboxEntry {
|
||||
path: compile_scoped_filesystem_path(path, subpath, startup_warnings)?,
|
||||
access: *access,
|
||||
missing_path_behavior: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,6 +577,7 @@ fn read_write_trailing_glob_suffix_compiles_as_subpath() -> std::io::Result<()>
|
||||
value: FileSystemSpecialPath::project_roots(Some("docs".into())),
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
}]),
|
||||
"trailing /** should compile as a subtree path instead of a glob pattern"
|
||||
);
|
||||
|
||||
@@ -152,18 +152,21 @@ fn workspace_write_permission_profile_with_private_denials() -> PermissionProfil
|
||||
value: FileSystemSpecialPath::project_roots(/*subpath*/ None),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::project_roots(Some("private".to_string())),
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::GlobPattern {
|
||||
pattern: project_roots_glob_pattern(Path::new("private/**")),
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]),
|
||||
NetworkSandboxPolicy::Restricted,
|
||||
|
||||
@@ -1182,12 +1182,14 @@ fn managed_cwd_write_profile_has_filesystem_restrictions() {
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::project_roots(/*subpath*/ None),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
@@ -1208,6 +1210,7 @@ fn managed_unresolvable_write_profile_has_filesystem_restrictions() {
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
@@ -1217,6 +1220,7 @@ fn managed_unresolvable_write_profile_has_filesystem_restrictions() {
|
||||
),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
@@ -1237,6 +1241,7 @@ fn managed_full_disk_write_profile_has_no_filesystem_restrictions() {
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
}]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
&file_system_sandbox_policy,
|
||||
|
||||
@@ -142,12 +142,14 @@ fn writable_windows_policy_without_sandbox_backend_still_requires_approval() {
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::project_roots(/*subpath*/ None),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
|
||||
@@ -441,6 +441,7 @@ fn windows_restricted_token_rejects_managed_root_write_profiles() {
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
@@ -512,6 +513,7 @@ fn windows_elevated_allows_split_restricted_read_policies() {
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Path { path: docs },
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
@@ -543,6 +545,7 @@ fn windows_restricted_token_rejects_split_only_filesystem_policies() {
|
||||
),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Path {
|
||||
@@ -550,6 +553,7 @@ fn windows_restricted_token_rejects_split_only_filesystem_policies() {
|
||||
.expect("absolute docs"),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
@@ -582,6 +586,7 @@ fn windows_restricted_token_rejects_root_write_read_only_carveouts() {
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Path {
|
||||
@@ -589,6 +594,7 @@ fn windows_restricted_token_rejects_root_write_read_only_carveouts() {
|
||||
.expect("absolute docs"),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
@@ -624,6 +630,7 @@ fn windows_restricted_token_supports_full_read_split_write_read_carveouts() {
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Special {
|
||||
@@ -632,10 +639,12 @@ fn windows_restricted_token_supports_full_read_split_write_read_carveouts() {
|
||||
),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Path { path: docs.clone() },
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
@@ -679,6 +688,7 @@ fn windows_restricted_token_rejects_unreadable_split_carveouts() {
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Special {
|
||||
@@ -687,10 +697,12 @@ fn windows_restricted_token_rejects_unreadable_split_carveouts() {
|
||||
),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Path { path: blocked },
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
@@ -725,6 +737,7 @@ fn windows_elevated_supports_split_restricted_read_roots() {
|
||||
.expect("absolute docs"),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
@@ -761,6 +774,7 @@ fn windows_elevated_supports_split_write_read_carveouts() {
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Special {
|
||||
@@ -769,6 +783,7 @@ fn windows_elevated_supports_split_write_read_carveouts() {
|
||||
),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Path {
|
||||
@@ -776,6 +791,7 @@ fn windows_elevated_supports_split_write_read_carveouts() {
|
||||
.expect("absolute docs"),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
@@ -803,6 +819,52 @@ fn windows_elevated_supports_split_write_read_carveouts() {
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[test]
|
||||
fn windows_workspace_defaults_do_not_hide_explicit_metadata_carveouts() {
|
||||
let temp_dir = tempfile::TempDir::new().expect("tempdir");
|
||||
let cwd = temp_dir.path().canonicalize().expect("canonical cwd").abs();
|
||||
|
||||
let default_profile = PermissionProfile::workspace_write();
|
||||
let default_overrides = resolve_windows_elevated_filesystem_overrides(
|
||||
SandboxType::WindowsRestrictedToken,
|
||||
&default_profile,
|
||||
&cwd,
|
||||
/*use_windows_elevated_backend*/ true,
|
||||
)
|
||||
.expect("resolve workspace defaults");
|
||||
assert!(
|
||||
default_overrides.is_none_or(|overrides| overrides.additional_deny_write_paths.is_empty())
|
||||
);
|
||||
|
||||
for name in codex_protocol::permissions::PROTECTED_METADATA_PATH_NAMES {
|
||||
let (mut explicit_policy, network_policy) = default_profile.to_runtime_permissions();
|
||||
explicit_policy
|
||||
.entries
|
||||
.push(codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Special {
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::project_roots(Some(
|
||||
(*name).into(),
|
||||
)),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
});
|
||||
let explicit_profile =
|
||||
PermissionProfile::from_runtime_permissions(&explicit_policy, network_policy);
|
||||
|
||||
let overrides = resolve_windows_elevated_filesystem_overrides(
|
||||
SandboxType::WindowsRestrictedToken,
|
||||
&explicit_profile,
|
||||
&cwd,
|
||||
/*use_windows_elevated_backend*/ true,
|
||||
)
|
||||
.expect("resolve explicit metadata carveout")
|
||||
.expect("explicit metadata carveout needs an override");
|
||||
assert_eq!(overrides.additional_deny_write_paths, vec![cwd.join(name)]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn windows_elevated_supports_unreadable_split_carveouts() {
|
||||
let temp_dir = tempfile::TempDir::new().expect("tempdir");
|
||||
@@ -815,6 +877,7 @@ fn windows_elevated_supports_unreadable_split_carveouts() {
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Special {
|
||||
@@ -823,6 +886,7 @@ fn windows_elevated_supports_unreadable_split_carveouts() {
|
||||
),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Path {
|
||||
@@ -830,6 +894,7 @@ fn windows_elevated_supports_unreadable_split_carveouts() {
|
||||
.expect("absolute blocked"),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
@@ -874,6 +939,7 @@ fn windows_elevated_supports_unreadable_globs() {
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Special {
|
||||
@@ -882,12 +948,14 @@ fn windows_elevated_supports_unreadable_globs() {
|
||||
),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::GlobPattern {
|
||||
pattern: "**/*.env".to_string(),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
@@ -927,6 +995,7 @@ fn windows_elevated_rejects_reopened_writable_descendants() {
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Special {
|
||||
@@ -935,6 +1004,7 @@ fn windows_elevated_rejects_reopened_writable_descendants() {
|
||||
),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Path {
|
||||
@@ -942,6 +1012,7 @@ fn windows_elevated_rejects_reopened_writable_descendants() {
|
||||
.expect("absolute docs"),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Path {
|
||||
@@ -949,6 +1020,7 @@ fn windows_elevated_rejects_reopened_writable_descendants() {
|
||||
.expect("absolute nested"),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
|
||||
@@ -473,18 +473,21 @@ async fn build_guardian_prompt_includes_parent_turn_denied_reads() -> anyhow::Re
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: denied_root.clone(),
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::GlobPattern {
|
||||
pattern: denied_glob.clone(),
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]),
|
||||
NetworkSandboxPolicy::Restricted,
|
||||
|
||||
@@ -230,12 +230,14 @@ fn explicit_unreadable_paths_prevent_auto_approval_for_external_sandbox() {
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: blocked_absolute,
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -278,12 +280,14 @@ fn explicit_read_only_subpaths_prevent_auto_approval_for_external_sandbox() {
|
||||
value: FileSystemSpecialPath::project_roots(/*subpath*/ None),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: docs_absolute,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -327,6 +331,7 @@ fn missing_project_dot_codex_config_requires_approval() {
|
||||
path: cwd.join(".codex"),
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
});
|
||||
|
||||
assert!(!is_write_patch_constrained_to_writable_paths(
|
||||
|
||||
@@ -98,6 +98,7 @@ fn root_write_managed_profile_with_enabled_network_is_untagged() {
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
}],
|
||||
glob_scan_max_depth: None,
|
||||
},
|
||||
@@ -148,6 +149,7 @@ fn profile_policy_tag_reports_closest_legacy_mode() {
|
||||
path: writable_root,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
}],
|
||||
},
|
||||
NetworkSandboxPolicy::Restricted,
|
||||
|
||||
@@ -4606,10 +4606,12 @@ async fn session_configuration_apply_preserves_profile_file_system_policy_on_cwd
|
||||
value: FileSystemSpecialPath::project_roots(/*subpath*/ None),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path { path: docs_dir },
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let network_sandbox_policy = NetworkSandboxPolicy::from(&sandbox_policy);
|
||||
@@ -4653,6 +4655,7 @@ async fn session_configuration_apply_permission_profile_preserves_existing_deny_
|
||||
pattern: "**/*.env".to_string(),
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
};
|
||||
let mut existing_file_system_policy =
|
||||
FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(
|
||||
@@ -4716,6 +4719,7 @@ async fn session_configuration_apply_permission_profile_accepts_direct_write_roo
|
||||
path: external_write_path.clone(),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
}]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
&file_system_sandbox_policy,
|
||||
@@ -4965,12 +4969,14 @@ async fn session_configuration_apply_preserves_absolute_cwd_write_root_on_cwd_up
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: original_cwd.clone(),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
session_configuration
|
||||
@@ -6208,6 +6214,7 @@ async fn request_permissions_tool_resolves_relative_paths_against_selected_envir
|
||||
path: environment_cwd.join("relative.txt"),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
}],
|
||||
glob_scan_max_depth: None,
|
||||
}),
|
||||
@@ -6294,6 +6301,7 @@ async fn request_permissions_response_materializes_session_cwd_grants_before_rec
|
||||
value: FileSystemSpecialPath::project_roots(/*subpath*/ None),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
}],
|
||||
glob_scan_max_depth: None,
|
||||
}),
|
||||
@@ -8858,6 +8866,7 @@ fn file_system_policy_with_unreadable_glob(turn_context: &TurnContext) -> FileSy
|
||||
pattern: format!("{cwd_display}/**/*.env"),
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
});
|
||||
policy
|
||||
}
|
||||
|
||||
@@ -444,12 +444,14 @@ mod tests {
|
||||
value: FileSystemSpecialPath::project_roots(/*subpath*/ None),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::GlobPattern {
|
||||
pattern: "**/*.env".to_string(),
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
],
|
||||
glob_scan_max_depth: None,
|
||||
|
||||
@@ -2283,6 +2283,7 @@ async fn spawn_agent_reapplies_runtime_sandbox_after_role_config() {
|
||||
pattern: "**/.env".to_string(),
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
});
|
||||
let expected_network_sandbox_policy = NetworkSandboxPolicy::from(&expected_sandbox);
|
||||
let expected_permission_profile = PermissionProfile::from_runtime_permissions_with_enforcement(
|
||||
|
||||
@@ -69,6 +69,7 @@ fn read_only_file_system_sandbox_policy() -> FileSystemSandboxPolicy {
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
}])
|
||||
}
|
||||
|
||||
@@ -79,12 +80,14 @@ fn denied_read_file_system_sandbox_policy() -> FileSystemSandboxPolicy {
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::GlobPattern {
|
||||
pattern: "**/*.env".to_string(),
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
])
|
||||
}
|
||||
@@ -299,12 +302,14 @@ fn shell_request_escalation_execution_is_explicit() {
|
||||
path: AbsolutePathBuf::from_absolute_path("/tmp/original/output").unwrap(),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: AbsolutePathBuf::from_absolute_path("/tmp/secret").unwrap(),
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let network_sandbox_policy = NetworkSandboxPolicy::Restricted;
|
||||
|
||||
@@ -151,6 +151,7 @@ fn deny_read_blocks_explicit_escalation_and_policy_bypass() {
|
||||
pattern: "**/*.env".to_string(),
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
}]);
|
||||
|
||||
assert_eq!(
|
||||
|
||||
Reference in new issue
Block a user