## Why Before this change, an escalation approval could say that a command should be rerun, but it could not carry the sandbox configuration that should still apply when the escalated command is actually spawned. That left an unsafe gap in the `zsh-fork` skill path: skill scripts under `scripts/` that did not declare permissions could be escalated without a sandbox, and scripts that did declare permissions could lose their bounded sandbox on rerun or cached session approval. This PR extends the escalation protocol so approvals can optionally carry sandbox configuration all the way through execution. That lets the shell runtime preserve the intended sandbox instead of silently widening access. We likely want a single permissions type for this codepath eventually, probably centered on `Permissions`. For now, the protocol needs to represent both the existing `PermissionProfile` form and the fuller `Permissions` form, so this introduces a temporary disjoint union, `EscalationPermissions`, to carry either one. Further, this means that today, a skill either: - does not declare any permissions, in which case it is run using the default sandbox for the turn - specifies permissions, in which case the skill is run using that exact sandbox, which might be more restrictive than the default sandbox for the turn We will likely change the skill's permissions to be additive to the existing permissions for the turn. ## What Changed - Added `EscalationPermissions` to `codex-protocol` so escalation requests can carry either a `PermissionProfile` or a full `Permissions` payload. - Added an explicit `EscalationExecution` mode to the shell escalation protocol so reruns distinguish between `Unsandboxed`, `TurnDefault`, and `Permissions(...)` instead of overloading `None`. - Updated `zsh-fork` shell reruns to resolve `TurnDefault` at execution time, which keeps ordinary `UseDefault` commands on the turn sandbox and preserves turn-level macOS seatbelt profile extensions. - Updated the `zsh-fork` skill path so a skill with no declared permissions inherits the conversation's effective sandbox instead of escalating unsandboxed. - Updated the `zsh-fork` skill path so a skill with declared permissions reruns with exactly those permissions, including when a cached session approval is reused. ## Testing - Added unit coverage in `core/src/tools/runtimes/shell/unix_escalation.rs` for the explicit `UseDefault` / `RequireEscalated` / `WithAdditionalPermissions` execution mapping. - Added unit coverage in `core/src/tools/runtimes/shell/unix_escalation.rs` for macOS seatbelt extension preservation in both the `TurnDefault` and explicit-permissions rerun paths. - Added integration coverage in `core/tests/suite/skill_approval.rs` for permissionless skills inheriting the turn sandbox and explicit skill permissions remaining bounded across cached approval reuse.
36 lines
962 B
TOML
36 lines
962 B
TOML
[package]
|
|
edition.workspace = true
|
|
license.workspace = true
|
|
name = "codex-shell-escalation"
|
|
version.workspace = true
|
|
|
|
[[bin]]
|
|
name = "codex-execve-wrapper"
|
|
path = "src/bin/main_execve_wrapper.rs"
|
|
|
|
[dependencies]
|
|
anyhow = { workspace = true }
|
|
async-trait = { workspace = true }
|
|
clap = { workspace = true, features = ["derive"] }
|
|
codex-protocol = { workspace = true }
|
|
codex-utils-absolute-path = { workspace = true }
|
|
libc = { workspace = true }
|
|
serde = { workspace = true, features = ["derive"] }
|
|
serde_json = { workspace = true }
|
|
socket2 = { workspace = true, features = ["all"] }
|
|
tokio = { workspace = true, features = [
|
|
"io-std",
|
|
"net",
|
|
"macros",
|
|
"process",
|
|
"rt-multi-thread",
|
|
"signal",
|
|
"time",
|
|
] }
|
|
tokio-util = { workspace = true }
|
|
tracing = { workspace = true }
|
|
tracing-subscriber = { workspace = true, features = ["env-filter", "fmt"] }
|
|
|
|
[dev-dependencies]
|
|
pretty_assertions = { workspace = true }
|
|
tempfile = { workspace = true }
|