Conversation
bc7e463 to
41ebc4d
Compare
8b4d2a2 to
e5f2e57
Compare
a9a5407 to
e600010
Compare
## Why `Permissions` should not store a separate `PermissionProfile` that can drift from the constrained `SandboxPolicy` and network settings. The active profile needs to be derived from the same constrained values that already honor `requirements.toml`. ## What changed This adds derivation of the active `PermissionProfile` from the constrained runtime permission settings and exposes that derived value through config snapshots and thread state. The app-server can then report the active profile without introducing a second source of truth. ## Verification - `cargo test -p codex-core --test all permissions_messages -- --nocapture` - `cargo test -p codex-core --test all request_permissions -- --nocapture` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/18277). * #18288 * #18287 * #18286 * #18285 * #18284 * #18283 * #18282 * #18281 * #18280 * #18279 * #18278 * __->__ #18277
134b830 to
f16904c
Compare
bbabb69 to
ab39876
Compare
37a49c3 to
d9bfa96
Compare
cf96acd to
99782a9
Compare
## Why `PermissionProfile` is becoming the canonical permissions shape shared by core and app-server. After app-server responses expose the active profile, clients need to be able to send that same shape back when starting, resuming, forking, or overriding a turn instead of translating through the legacy `sandbox`/`sandboxPolicy` shorthands. This still needs to preserve the existing requirements/platform enforcement model. A profile-shaped request can be downgraded or rejected by constraints, but the server should keep the user's elevated-access intent for project trust decisions. Turn-level profile overrides also need to retain existing read protections, including deny-read entries and bounded glob-scan metadata, so a permission override cannot accidentally drop configured protections such as `**/*.env = deny`. ## What changed - Adds optional `permissionProfile` request fields to `thread/start`, `thread/resume`, `thread/fork`, and `turn/start`. - Rejects ambiguous requests that specify both `permissionProfile` and the legacy `sandbox`/`sandboxPolicy` fields, including running-thread resume requests. - Converts profile-shaped overrides into core runtime filesystem/network permissions while continuing to derive the constrained legacy sandbox projection used by existing execution paths. - Preserves project-trust intent for profile overrides that are equivalent to workspace-write or full-access sandbox requests. - Preserves existing deny-read entries and `globScanMaxDepth` when applying turn-level `permissionProfile` overrides. - Updates app-server docs plus generated JSON/TypeScript schema fixtures and regression coverage. ## Verification - `cargo test -p codex-app-server-protocol schema_fixtures` - `cargo test -p codex-core session_configuration_apply_permission_profile_preserves_existing_deny_read_entries` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/18279). * #18288 * #18287 * #18286 * #18285 * #18284 * #18283 * #18282 * #18281 * #18280 * __->__ #18279
939a7f0 to
e4813ba
Compare
94ec857 to
33269ed
Compare
| ) = if let Some(permission_profile) = permission_profile { | ||
| let permission_profile = | ||
| codex_protocol::models::PermissionProfile::from(permission_profile); | ||
| let sandbox_policy = match permission_profile.to_legacy_sandbox_policy(&sandbox_cwd) { |
There was a problem hiding this comment.
[P1] Resolve command permission profiles against the command cwd
command/exec resolves the requested process cwd above, but this new permissionProfile path still materializes profile entries against self.config.cwd via sandbox_cwd. The command API docs show permissionProfile using current_working_directory next to the request cwd, and profiles can also carry cwd-relative deny globs. With the current code, a command running in cwd: "subdir" with :cwd write grants the server root instead of the command cwd, while relative deny globs constrain the wrong tree. That can deny the intended command or grant broader writes than the client requested. Use the resolved command cwd as the policy cwd for command-specific permission profiles, or require/materialize only cwd-independent profile entries before accepting them.
There was a problem hiding this comment.
Suggested minimal patch:
- let sandbox_cwd = self.config.cwd.clone();
+ let sandbox_cwd = if permission_profile.is_some() {
+ cwd.clone()
+ } else {
+ self.config.cwd.clone()
+ };That keeps the legacy/default command/exec paths resolving policy-relative entries against the configured server cwd, while making the new command-specific permissionProfile path use the resolved process cwd for both to_legacy_sandbox_policy(...) and the later build_exec_request(...) call.
Why
command/execis another app-server entry point that can run under caller-provided permissions. It needs to acceptPermissionProfiledirectly so command execution is not left behind onSandboxPolicywhile thread APIs move forward.Command-level profiles also need to preserve the semantics clients expect from profile-relative paths.
:cwdand cwd-relative deny globs should be anchored to the resolved command cwd for a command-specific profile, while configured deny-read restrictions such as**/*.env = nonestill need to be enforced because they can come from config or requirements rather than the command override itself.What Changed
This adds
permissionProfiletoCommandExecParams, rejects requests that combine it withsandboxPolicy, and converts accepted profiles into the runtime filesystem/network permissions used for command execution.When a command supplies a profile, the app-server resolves that profile against the command cwd instead of the thread/server cwd. It also preserves configured deny-read entries and
globScanMaxDepthon the effective filesystem policy so one-off command overrides cannot drop those read protections. The PR also updates app-server docs/schema fixtures and adds command-exec coverage for accepted, rejected, cwd-scoped, and deny-read-preserving profile paths.Verification
cargo test -p codex-app-server command_exec_permission_profile_cwd_uses_command_cwdcargo test -p codex-app-server command_profile_preserves_configured_deny_read_restrictionscargo test -p codex-app-server command_exec_accepts_permission_profilecargo test -p codex-app-server command_exec_rejects_sandbox_policy_with_permission_profilejust fix -p codex-app-serverStack created with Sapling. Best reviewed with ReviewStack.