mirror of
https://github.com/openai/codex.git
synced 2026-11-07 20:30:33 +00:00
Allow stdin review under active grants with sandbox prompts disabled (#54119)
## Why With granular sandbox approvals disabled, `write_stdin` rejected input to terminals retaining additional permissions even when those permissions were still granted. ## What changed Let input reach approval review when the terminal's retained permissions match active grants for its environment. Require identical filesystem grants, including entry order, and an active network grant when retained permissions enable network access. Each input still requires review. Keep rejecting input when retained authority is no longer covered or the approval policy changes to `Never`. ## Testing Add regression coverage for user and Guardian review, turn grant expiry, session grants, and switching to `Never`. Cover filesystem restrictions, protected metadata, symlinks, and ordered denials, and verify that rejected input never reaches the terminal. GitOrigin-RevId: 9abf7da8d03b1526d26ca2a718e36349a255330b
This commit is contained in:
@@ -20,6 +20,7 @@ use codex_protocol::models::AdditionalPermissionProfile;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::models::SandboxPermissions;
|
||||
use codex_protocol::permissions::NetworkSandboxPolicy;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_sandboxing::policy_transforms::effective_permission_profile;
|
||||
use codex_sandboxing::policy_transforms::merge_permission_profiles;
|
||||
|
||||
@@ -237,6 +238,39 @@ impl ProcessEntry {
|
||||
let reason = permissions
|
||||
.approval_reason(sandbox_permissions)
|
||||
.map_err(approval_error)?;
|
||||
// A scoped grant can authorize retained authority without permitting new
|
||||
// sandbox escalations. Still review every input, and only recognize grants
|
||||
// that remain active for this terminal's environment with the same policy.
|
||||
let additional_permissions_preapproved = matches!(
|
||||
context.step_context.turn.approval_policy(),
|
||||
AskForApproval::Granular(policy) if !policy.sandbox_approval
|
||||
) && sandbox_permissions
|
||||
== SandboxPermissions::WithAdditionalPermissions
|
||||
&& permissions
|
||||
.additional_permissions
|
||||
.as_ref()
|
||||
.zip(
|
||||
context
|
||||
.step_context
|
||||
.turn
|
||||
.granted_permissions(&self.environment_id),
|
||||
)
|
||||
.is_some_and(|(retained, current_grants)| {
|
||||
// Root containment does not prove filesystem coverage: child
|
||||
// restrictions, protected metadata, and symlinks can differ.
|
||||
// Require the original filesystem grants, including their order.
|
||||
retained.file_system == current_grants.file_system
|
||||
&& (retained
|
||||
.network
|
||||
.as_ref()
|
||||
.and_then(|network| network.enabled)
|
||||
!= Some(true)
|
||||
|| current_grants
|
||||
.network
|
||||
.as_ref()
|
||||
.and_then(|network| network.enabled)
|
||||
== Some(true))
|
||||
});
|
||||
let action = ApprovalAction::WriteStdin {
|
||||
id: self.call_id.clone(),
|
||||
approval_id: context.call_id.clone(),
|
||||
@@ -247,6 +281,7 @@ impl ProcessEntry {
|
||||
tty: self.tty,
|
||||
sandbox_permissions,
|
||||
additional_permissions: permissions.additional_permissions.clone(),
|
||||
additional_permissions_preapproved,
|
||||
};
|
||||
Ok(Some((action, reason)))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user