mirror of
https://github.com/openai/codex.git
synced 2026-05-05 20:07:02 +00:00
permissions: remove legacy read-only access modes (#19449)
## Why `ReadOnlyAccess` was a transitional legacy shape on `SandboxPolicy`: `FullAccess` meant the historical read-only/workspace-write modes could read the full filesystem, while `Restricted` tried to carry partial readable roots. The partial-read model now belongs in `FileSystemSandboxPolicy` and `PermissionProfile`, so keeping it on `SandboxPolicy` makes every legacy projection reintroduce lossy read-root bookkeeping and creates unnecessary noise in the rest of the permissions migration. This PR makes the legacy policy model narrower and explicit: `SandboxPolicy::ReadOnly` and `SandboxPolicy::WorkspaceWrite` represent the old full-read sandbox modes only. Split readable roots, deny-read globs, and platform-default/minimal read behavior stay in the runtime permissions model. ## What changed - Removes `ReadOnlyAccess` from `codex_protocol::protocol::SandboxPolicy`, including the generated `access` and `readOnlyAccess` API fields. - Updates legacy policy/profile conversions so restricted filesystem reads are represented only by `FileSystemSandboxPolicy` / `PermissionProfile` entries. - Keeps app-server v2 compatible with legacy `fullAccess` read-access payloads by accepting and ignoring that no-op shape, while rejecting legacy `restricted` read-access payloads instead of silently widening them to full-read legacy policies. - Carries Windows sandbox platform-default read behavior with an explicit override flag instead of depending on `ReadOnlyAccess::Restricted`. - Refreshes generated app-server schema/types and updates tests/docs for the simplified legacy policy shape. ## Verification - `cargo check -p codex-app-server-protocol --tests` - `cargo check -p codex-windows-sandbox --tests` - `cargo test -p codex-app-server-protocol sandbox_policy_` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/19449). * #19395 * #19394 * #19393 * #19392 * #19391 * __->__ #19449
This commit is contained in:
@@ -32,7 +32,7 @@ use globset::GlobSet;
|
||||
use globset::GlobSetBuilder;
|
||||
|
||||
/// Linux "platform defaults" that keep common system binaries and dynamic
|
||||
/// libraries readable when `ReadOnlyAccess::Restricted` requests them.
|
||||
/// libraries readable when a split filesystem policy requests `:minimal`.
|
||||
///
|
||||
/// These are intentionally system-level paths only (plus Nix store roots) so
|
||||
/// `include_platform_defaults` does not silently widen access to user data.
|
||||
@@ -1002,7 +1002,6 @@ mod tests {
|
||||
use codex_protocol::protocol::FileSystemSandboxEntry;
|
||||
use codex_protocol::protocol::FileSystemSandboxPolicy;
|
||||
use codex_protocol::protocol::FileSystemSpecialPath;
|
||||
use codex_protocol::protocol::ReadOnlyAccess;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use pretty_assertions::assert_eq;
|
||||
@@ -1371,7 +1370,6 @@ mod tests {
|
||||
AbsolutePathBuf::try_from(existing_root.as_path()).expect("absolute existing root"),
|
||||
AbsolutePathBuf::try_from(missing_root.as_path()).expect("absolute missing root"),
|
||||
],
|
||||
read_only_access: Default::default(),
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
@@ -1402,7 +1400,6 @@ mod tests {
|
||||
fn mounts_dev_before_writable_dev_binds() {
|
||||
let sandbox_policy = SandboxPolicy::WorkspaceWrite {
|
||||
writable_roots: vec![AbsolutePathBuf::try_from(Path::new("/dev")).expect("/dev path")],
|
||||
read_only_access: Default::default(),
|
||||
network_access: false,
|
||||
exclude_tmpdir_env_var: true,
|
||||
exclude_slash_tmp: true,
|
||||
@@ -1449,23 +1446,17 @@ mod tests {
|
||||
let readable_root = temp_dir.path().join("readable");
|
||||
std::fs::create_dir(&readable_root).expect("create readable root");
|
||||
|
||||
let policy = SandboxPolicy::ReadOnly {
|
||||
access: ReadOnlyAccess::Restricted {
|
||||
include_platform_defaults: false,
|
||||
readable_roots: vec![
|
||||
AbsolutePathBuf::try_from(readable_root.as_path())
|
||||
.expect("absolute readable root"),
|
||||
],
|
||||
let policy = FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: AbsolutePathBuf::try_from(readable_root.as_path())
|
||||
.expect("absolute readable root"),
|
||||
},
|
||||
network_access: false,
|
||||
};
|
||||
access: FileSystemAccessMode::Read,
|
||||
}]);
|
||||
|
||||
let args = create_filesystem_args(
|
||||
&FileSystemSandboxPolicy::from(&policy),
|
||||
temp_dir.path(),
|
||||
NO_UNREADABLE_GLOB_SCAN_MAX_DEPTH,
|
||||
)
|
||||
.expect("filesystem args");
|
||||
let args =
|
||||
create_filesystem_args(&policy, temp_dir.path(), NO_UNREADABLE_GLOB_SCAN_MAX_DEPTH)
|
||||
.expect("filesystem args");
|
||||
|
||||
assert_eq!(args.args[0..4], ["--tmpfs", "/", "--dev", "/dev"]);
|
||||
|
||||
@@ -1483,23 +1474,16 @@ mod tests {
|
||||
#[test]
|
||||
fn restricted_read_only_with_platform_defaults_includes_usr_when_present() {
|
||||
let temp_dir = TempDir::new().expect("temp dir");
|
||||
let policy = SandboxPolicy::ReadOnly {
|
||||
access: ReadOnlyAccess::Restricted {
|
||||
include_platform_defaults: true,
|
||||
readable_roots: Vec::new(),
|
||||
let policy = FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::Minimal,
|
||||
},
|
||||
network_access: false,
|
||||
};
|
||||
access: FileSystemAccessMode::Read,
|
||||
}]);
|
||||
|
||||
// `ReadOnlyAccess::Restricted` always includes `cwd` as a readable
|
||||
// root. Using `"/"` here would intentionally collapse to broad read
|
||||
// access, so use a non-root cwd to exercise the restricted path.
|
||||
let args = create_filesystem_args(
|
||||
&FileSystemSandboxPolicy::from(&policy),
|
||||
temp_dir.path(),
|
||||
NO_UNREADABLE_GLOB_SCAN_MAX_DEPTH,
|
||||
)
|
||||
.expect("filesystem args");
|
||||
let args =
|
||||
create_filesystem_args(&policy, temp_dir.path(), NO_UNREADABLE_GLOB_SCAN_MAX_DEPTH)
|
||||
.expect("filesystem args");
|
||||
|
||||
assert!(
|
||||
args.args
|
||||
|
||||
Reference in New Issue
Block a user