Honor granular sandbox approvals in unified exec (#40024)

## What changed

- Use the shared approval-policy check for unified exec sandbox escalation so
  `require_escalated` commands can prompt when granular `sandbox_approval` is
  enabled and remain rejected when it is disabled.
- Add an approval scenario covering sandbox escalation with granular approvals
  enabled.

GitOrigin-RevId: 98907960cd9df181e1b2fd9d7fea11fa3c0ed7e6
This commit is contained in:
Sean Huang
2026-08-21 21:42:22 +00:00
committed by copyberry
parent 6143217c67
commit 9445ef227e
2 changed files with 32 additions and 2 deletions

View File

@@ -1,6 +1,7 @@
use std::path::Path;
use std::sync::Arc;
use crate::exec_policy::prompt_is_rejected_by_policy;
use crate::function_tool::FunctionCallError;
use crate::maybe_emit_implicit_skill_invocation;
use crate::tools::context::ExecCommandToolOutput;
@@ -279,10 +280,11 @@ impl ExecCommandHandler {
.sandbox_permissions
.requests_sandbox_override()
&& !effective_additional_permissions.permissions_preapproved
&& !matches!(
&& prompt_is_rejected_by_policy(
context.step_context.turn.approval_policy(),
codex_protocol::protocol::AskForApproval::OnRequest
/*prompt_is_rule*/ false,
)
.is_some()
{
let approval_policy = context.step_context.turn.approval_policy();
manager.release_process_id(process_id).await;

View File

@@ -1074,6 +1074,34 @@ fn scenarios() -> Vec<ScenarioSpec> {
output_contains: "rejected by user",
},
},
ScenarioSpec {
name: "simple_command_escalation_granular_sandbox_enabled_requires_approval",
approval_policy: Granular(GranularApprovalConfig {
sandbox_approval: true,
rules: true,
skill_approval: true,
request_permissions: true,
mcp_elicitations: true,
}),
sandbox_policy: workspace_write(false),
action: ActionKind::RunCommand {
command: "echo known-safe-escalation",
},
sandbox_permissions: SandboxPermissions::RequireEscalated,
features: vec![],
model_override: Some("gpt-5.2"),
outcome: Outcome::ExecApprovalWithAmendment {
decision: ReviewDecision::denied("rejected by user"),
expected_reason: None,
expected_execpolicy_amendment: Some(ExpectedExecPolicyAmendment::Prefix(&[
"echo",
"known-safe-escalation",
])),
},
expectation: Expectation::CommandFailure {
output_contains: "rejected by user",
},
},
ScenarioSpec {
name: "simple_command_escalation_granular_sandbox_disabled_rejects",
approval_policy: Granular(GranularApprovalConfig {