mirror of
https://github.com/openai/codex.git
synced 2026-11-05 16:29:31 +00:00
core: derive built-in permission profiles from raw policies (#25739)
## Why
Permission profiles that extend a built-in profile should behave like
other TOML inheritance: parent entries provide defaults, and child keys
override matching fields before the profile is compiled.
That was not true for `:workspace`. Previously, a profile with `extends
= ":workspace"` seeded the compiled runtime
`PermissionProfile::workspace_write()` policy and then appended child
filesystem entries. A child override such as `":tmpdir" = "read"`
therefore left the inherited `":tmpdir" = "write"` entry in the final
policy. Since same-target `write` wins over `read` during runtime
resolution, the child override was ineffective.
This also needs a clear source of truth for the built-in profiles. The
protocol-level sandbox policy constructors now define the raw built-in
filesystem entries, and both `PermissionProfile` presets and
config-profile inheritance derive from those same values.
## What Changed
- Add a canonical `FileSystemSandboxPolicy::read_only()` constructor
while keeping the read-only and workspace-write raw filesystem entries
explicit and independent.
- Derive `PermissionProfile::read_only()` from
`FileSystemSandboxPolicy::read_only()`;
`PermissionProfile::workspace_write()` continues to derive from
`FileSystemSandboxPolicy::workspace_write()`.
- Build extensible `:read-only` and `:workspace` parent profiles by
projecting those canonical sandbox policies into
`PermissionProfileToml`, then merge user overrides at the TOML layer
before compilation.
- Add config parsing support for `:slash_tmp` so the built-in
`:workspace` parent can be expressed in the same TOML-shaped filesystem
table as user profiles.
- Document that `PermissionsToml::resolve_profile()` returns an
already-merged `PermissionProfileToml`, and return that profile directly
after removing the resolved-profile wrapper.
- Extend the config test for `extends = ":workspace"` to assert that
inherited `":slash_tmp" = "write"` is preserved and that a child
`":tmpdir" = "read"` entry replaces the inherited `write` entry.
## Verification
- `just test -p codex-config`
- `just test -p codex-protocol`
- `just test -p codex-core
permissions_profiles_resolve_extends_parent_first_with_child_overrides`
- `just test -p codex-core
default_permissions_profile_can_extend_builtin_workspace`
- `just test -p codex-core`
- Result: 2596 passed, 4 failed, 1 timed out.
- The failures were existing sandbox/environment-sensitive tests
unrelated to this permissions change:
`suite::user_shell_cmd::user_shell_command_does_not_set_network_sandbox_env_var`,
`suite::user_shell_cmd::user_shell_command_history_is_persisted_and_shared_with_model`,
`suite::abort_tasks::interrupt_persists_turn_aborted_marker_in_next_request`,
`suite::abort_tasks::interrupt_tool_records_history_entries`, and
`thread_manager::tests::start_thread_uses_all_default_environments_from_codex_home`.
This commit is contained in:
1 parent
ebb7980369
commit
593df8773d
7 files changed
+195
-74
No files matched your search
@@ -2357,7 +2357,13 @@ async fn default_permissions_profile_can_extend_builtin_workspace() -> std::io::
|
||||
description: None,
|
||||
extends: Some(BUILT_IN_PERMISSION_PROFILE_WORKSPACE.to_string()),
|
||||
workspace_roots: None,
|
||||
filesystem: None,
|
||||
filesystem: Some(FilesystemPermissionsToml {
|
||||
glob_scan_max_depth: None,
|
||||
entries: BTreeMap::from([(
|
||||
":tmpdir".to_string(),
|
||||
FilesystemPermissionToml::Access(FileSystemAccessMode::Read),
|
||||
)]),
|
||||
}),
|
||||
network: Some(NetworkToml {
|
||||
enabled: Some(true),
|
||||
..Default::default()
|
||||
@@ -2384,6 +2390,42 @@ async fn default_permissions_profile_can_extend_builtin_workspace() -> std::io::
|
||||
!policy.can_write_path_with_cwd(&cwd.path().join(".git"), cwd.path()),
|
||||
"expected profile extending :workspace to keep metadata carveouts, policy: {policy:?}"
|
||||
);
|
||||
assert!(
|
||||
policy.entries.iter().any(|entry| matches!(
|
||||
entry,
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::SlashTmp,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
}
|
||||
)),
|
||||
"expected profile extending :workspace to keep inherited :slash_tmp writes, policy: {policy:?}"
|
||||
);
|
||||
assert!(
|
||||
policy.entries.iter().any(|entry| matches!(
|
||||
entry,
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::Tmpdir,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
}
|
||||
)),
|
||||
"expected child :tmpdir read entry to replace the inherited write entry, policy: {policy:?}"
|
||||
);
|
||||
assert!(
|
||||
!policy.entries.iter().any(|entry| matches!(
|
||||
entry,
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::Tmpdir,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
}
|
||||
)),
|
||||
"expected inherited :tmpdir write entry to be removed, policy: {policy:?}"
|
||||
);
|
||||
assert_eq!(
|
||||
config.permissions.network_sandbox_policy(),
|
||||
NetworkSandboxPolicy::Enabled
|
||||
|
||||
Reference in new issue
Block a user