mirror of
https://github.com/openai/codex.git
synced 2026-10-19 17:28:46 +00:00
Allow approved escalation with environment-owned network policies (#46499)
## Why Environment-owned network policies rejected explicit sandbox escalation before command approval, and retained terminals that bypassed or no longer matched those policies required a new terminal. ## What changed - Allow `require_escalated` commands through the normal approval flow and bypass managed network proxies when full escalation is permitted. - Preserve denied-read restrictions, including the sandbox and network proxy needed to enforce them. - Track the network restrictions bypassed at launch and require escalation review for terminal input when launch permissions or network settings warrant it, instead of rejecting input outright. ## Testing Extend network approval coverage for approved and denied escalation, unproxied remote execution, and preserved denied-read restrictions. Add retained-terminal coverage verifying command and `write_stdin` approvals with restricted and unrestricted filesystems, and update the unit test for changed environment network policies to expect escalation review. GitOrigin-RevId: 50524b1bc4e3df58447c3c92fb9e50e69ed50cf8
This commit is contained in:
@@ -153,16 +153,6 @@ impl ToolOrchestrator {
|
||||
);
|
||||
let sandbox_config = environment.config();
|
||||
let owner_network_policy = sandbox_config.network_policy.is_some();
|
||||
if owner_network_policy
|
||||
&& tool
|
||||
.sandbox_permissions(req)
|
||||
.requires_escalated_permissions()
|
||||
{
|
||||
return Err(ToolError::Rejected(
|
||||
"attachment-owned network policy cannot be bypassed by sandbox escalation"
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
let workspace_roots = environment.workspace_roots();
|
||||
let executor_managed_process_sandbox = tool.uses_executor_managed_process_sandbox(req);
|
||||
let permission_profile = environment.permission_profile();
|
||||
@@ -236,8 +226,7 @@ impl ToolOrchestrator {
|
||||
}
|
||||
|
||||
// 2) First attempt under the selected sandbox.
|
||||
let unsandboxed_allowed =
|
||||
!owner_network_policy && unsandboxed_execution_allowed(&file_system_sandbox_policy);
|
||||
let unsandboxed_allowed = unsandboxed_execution_allowed(&file_system_sandbox_policy);
|
||||
let sandbox_override = if unsandboxed_allowed {
|
||||
sandbox_override_for_first_attempt(
|
||||
tool.sandbox_permissions(req),
|
||||
@@ -250,6 +239,8 @@ impl ToolOrchestrator {
|
||||
let network_approval_spec = tool.network_approval_spec(req, tool_ctx);
|
||||
// Offline owner attachments stay offline unless approved command permissions grant
|
||||
// networking. Existing enabled controller proxies remain independently authoritative.
|
||||
// Preserve this baseline even when escalation skips the execution proxy, so retained
|
||||
// terminals still record that their launch bypassed network restrictions.
|
||||
let managed_network_active = if owner_network_policy {
|
||||
turn_ctx
|
||||
.config
|
||||
@@ -257,13 +248,17 @@ impl ToolOrchestrator {
|
||||
.network
|
||||
.as_ref()
|
||||
.is_some_and(NetworkProxySpec::enabled)
|
||||
|| network_approval_spec.as_ref().is_some_and(|spec| {
|
||||
effective_network_sandbox_policy(
|
||||
|| (network_approval_spec.is_some()
|
||||
|| tool
|
||||
.sandbox_permissions(req)
|
||||
.requires_escalated_permissions())
|
||||
&& effective_network_sandbox_policy(
|
||||
permission_profile.network_sandbox_policy(),
|
||||
spec.trigger.additional_permissions.as_ref(),
|
||||
network_approval_spec
|
||||
.as_ref()
|
||||
.and_then(|spec| spec.trigger.additional_permissions.as_ref()),
|
||||
)
|
||||
.is_enabled()
|
||||
})
|
||||
} else {
|
||||
turn_ctx.network.is_some()
|
||||
};
|
||||
|
||||
@@ -229,9 +229,12 @@ impl<'a> ToolRuntime<UnifiedExecRequest, UnifiedExecAttempt> for UnifiedExecRunt
|
||||
req.sandbox_permissions,
|
||||
&file_system_sandbox_policy,
|
||||
);
|
||||
let network =
|
||||
managed_network_for_sandbox_permissions(req.network.as_ref(), sandbox_permissions)
|
||||
.cloned();
|
||||
// Explicit full escalation bypasses controller and attachment-owned network proxies.
|
||||
// Denied-read restrictions above can still require a sandboxed launch.
|
||||
if sandbox_permissions.requires_escalated_permissions() {
|
||||
return None;
|
||||
}
|
||||
let network = req.network.clone();
|
||||
// No-proxy fast path; owners still need a spec for execution-only proxies.
|
||||
if network.is_none() && req.turn_environment.config().network_policy.is_none() {
|
||||
return None;
|
||||
|
||||
@@ -115,13 +115,6 @@ impl TerminalPermissions {
|
||||
baseline: &PermissionProfile,
|
||||
) -> Result<SandboxPermissions, &'static str> {
|
||||
let bypassed = self.launch_permissions.requires_escalated_permissions();
|
||||
if current.environment_network.is_some()
|
||||
&& (bypassed || self.policy.environment_network != current.environment_network)
|
||||
{
|
||||
return Err(
|
||||
"this terminal cannot enforce the current environment-owned network restrictions; start a new terminal",
|
||||
);
|
||||
}
|
||||
// Approval cannot retrofit denied reads onto a running process. Unless
|
||||
// its sandbox still matches, start a new terminal under the current policy.
|
||||
if baseline
|
||||
|
||||
@@ -96,7 +96,7 @@ fn denied_reads_reject_file_system_changes_but_only_review_network_changes() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn captured_network_changes_require_review_or_a_new_terminal() -> anyhow::Result<()> {
|
||||
async fn captured_network_changes_require_review() -> anyhow::Result<()> {
|
||||
let (_session, mut turn) = make_session_and_context().await;
|
||||
let mut environment = turn.environments.primary().expect("environment").clone();
|
||||
environment.config_mut().permission_profile =
|
||||
@@ -151,9 +151,7 @@ async fn captured_network_changes_require_review_or_a_new_terminal() -> anyhow::
|
||||
);
|
||||
assert_eq!(
|
||||
permissions.review_requirement(¤t, environment.permission_profile()),
|
||||
Err(
|
||||
"this terminal cannot enforce the current environment-owned network restrictions; start a new terminal"
|
||||
)
|
||||
Ok(SandboxPermissions::RequireEscalated)
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user