From d609dfa2fce2855e01da4f68ce8c1ca0a2f48855 Mon Sep 17 00:00:00 2001 From: kevin zhao Date: Fri, 31 Oct 2025 17:15:50 -0400 Subject: [PATCH 1/3] escalating permissions --- codex-rs/core/src/tasks/user_shell.rs | 2 +- codex-rs/core/src/tools/handlers/shell.rs | 1 + codex-rs/core/src/tools/runtimes/shell.rs | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/codex-rs/core/src/tasks/user_shell.rs b/codex-rs/core/src/tasks/user_shell.rs index 0e57e1b728..cc48e3def6 100644 --- a/codex-rs/core/src/tasks/user_shell.rs +++ b/codex-rs/core/src/tasks/user_shell.rs @@ -82,7 +82,7 @@ impl SessionTask for UserShellCommandTask { command: shell_invocation, workdir: None, timeout_ms: None, - with_escalated_permissions: None, + with_escalated_permissions: Some(true), justification: None, }; diff --git a/codex-rs/core/src/tools/handlers/shell.rs b/codex-rs/core/src/tools/handlers/shell.rs index b97242a9a3..014a3a9c6e 100644 --- a/codex-rs/core/src/tools/handlers/shell.rs +++ b/codex-rs/core/src/tools/handlers/shell.rs @@ -219,6 +219,7 @@ impl ShellHandler { env: exec_params.env.clone(), with_escalated_permissions: exec_params.with_escalated_permissions, justification: exec_params.justification.clone(), + is_user_shell_command, }; let mut orchestrator = ToolOrchestrator::new(); let mut runtime = ShellRuntime::new(); diff --git a/codex-rs/core/src/tools/runtimes/shell.rs b/codex-rs/core/src/tools/runtimes/shell.rs index f29224fcc1..1e885ca689 100644 --- a/codex-rs/core/src/tools/runtimes/shell.rs +++ b/codex-rs/core/src/tools/runtimes/shell.rs @@ -34,6 +34,7 @@ pub struct ShellRequest { pub env: std::collections::HashMap, pub with_escalated_permissions: Option, pub justification: Option, + pub is_user_shell_command: bool, } impl ProvidesSandboxRetryData for ShellRequest { @@ -121,6 +122,9 @@ impl Approvable for ShellRuntime { policy: AskForApproval, sandbox_policy: &SandboxPolicy, ) -> bool { + if req.is_user_shell_command { + return false; + } if is_known_safe_command(&req.command) { return false; } From c7a3428986954f4ef03c8beeb0da24aba959d5c9 Mon Sep 17 00:00:00 2001 From: kevin zhao Date: Fri, 31 Oct 2025 17:27:35 -0400 Subject: [PATCH 2/3] fix --- codex-rs/core/src/tasks/user_shell.rs | 2 +- codex-rs/core/src/tools/runtimes/shell.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/codex-rs/core/src/tasks/user_shell.rs b/codex-rs/core/src/tasks/user_shell.rs index cc48e3def6..0e57e1b728 100644 --- a/codex-rs/core/src/tasks/user_shell.rs +++ b/codex-rs/core/src/tasks/user_shell.rs @@ -82,7 +82,7 @@ impl SessionTask for UserShellCommandTask { command: shell_invocation, workdir: None, timeout_ms: None, - with_escalated_permissions: Some(true), + with_escalated_permissions: None, justification: None, }; diff --git a/codex-rs/core/src/tools/runtimes/shell.rs b/codex-rs/core/src/tools/runtimes/shell.rs index 1e885ca689..8c31526699 100644 --- a/codex-rs/core/src/tools/runtimes/shell.rs +++ b/codex-rs/core/src/tools/runtimes/shell.rs @@ -150,7 +150,7 @@ impl Approvable for ShellRuntime { } fn wants_escalated_first_attempt(&self, req: &ShellRequest) -> bool { - req.with_escalated_permissions.unwrap_or(false) + req.is_user_shell_command || req.with_escalated_permissions.unwrap_or(false) } } From b81cb7ceb3c37b9d386fcb6cbf57e4b4cf09b372 Mon Sep 17 00:00:00 2001 From: zhao-oai Date: Sat, 1 Nov 2025 17:27:03 -0400 Subject: [PATCH 3/3] Fix sandbox detection for user shell commands (#6094) --- codex-rs/core/src/tasks/user_shell.rs | 5 ++++- codex-rs/core/src/tools/context.rs | 3 ++- codex-rs/core/src/tools/handlers/shell.rs | 7 +++++-- codex-rs/core/src/tools/router.rs | 5 ++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/codex-rs/core/src/tasks/user_shell.rs b/codex-rs/core/src/tasks/user_shell.rs index 0e57e1b728..eddfe00511 100644 --- a/codex-rs/core/src/tasks/user_shell.rs +++ b/codex-rs/core/src/tasks/user_shell.rs @@ -89,7 +89,10 @@ impl SessionTask for UserShellCommandTask { let tool_call = ToolCall { tool_name: USER_SHELL_TOOL_NAME.to_string(), call_id: Uuid::new_v4().to_string(), - payload: ToolPayload::LocalShell { params }, + payload: ToolPayload::LocalShell { + params, + is_user_shell_command: true, + }, }; let router = Arc::new(ToolRouter::from_config(&turn_context.tools_config, None)); diff --git a/codex-rs/core/src/tools/context.rs b/codex-rs/core/src/tools/context.rs index 029bacaa35..914617ec11 100644 --- a/codex-rs/core/src/tools/context.rs +++ b/codex-rs/core/src/tools/context.rs @@ -40,6 +40,7 @@ pub enum ToolPayload { }, LocalShell { params: ShellToolCallParams, + is_user_shell_command: bool, }, UnifiedExec { arguments: String, @@ -56,7 +57,7 @@ impl ToolPayload { match self { ToolPayload::Function { arguments } => Cow::Borrowed(arguments), ToolPayload::Custom { input } => Cow::Borrowed(input), - ToolPayload::LocalShell { params } => Cow::Owned(params.command.join(" ")), + ToolPayload::LocalShell { params, .. } => Cow::Owned(params.command.join(" ")), ToolPayload::UnifiedExec { arguments } => Cow::Borrowed(arguments), ToolPayload::Mcp { raw_arguments, .. } => Cow::Borrowed(raw_arguments), } diff --git a/codex-rs/core/src/tools/handlers/shell.rs b/codex-rs/core/src/tools/handlers/shell.rs index 014a3a9c6e..0cbe726290 100644 --- a/codex-rs/core/src/tools/handlers/shell.rs +++ b/codex-rs/core/src/tools/handlers/shell.rs @@ -82,7 +82,10 @@ impl ToolHandler for ShellHandler { ) .await } - ToolPayload::LocalShell { params } => { + ToolPayload::LocalShell { + params, + is_user_shell_command, + } => { let exec_params = Self::to_exec_params(params, turn.as_ref()); Self::run_exec_like( tool_name.as_str(), @@ -91,7 +94,7 @@ impl ToolHandler for ShellHandler { turn, tracker, call_id, - true, + is_user_shell_command, ) .await } diff --git a/codex-rs/core/src/tools/router.rs b/codex-rs/core/src/tools/router.rs index 19098aa80d..e301289069 100644 --- a/codex-rs/core/src/tools/router.rs +++ b/codex-rs/core/src/tools/router.rs @@ -120,7 +120,10 @@ impl ToolRouter { Ok(Some(ToolCall { tool_name: "local_shell".to_string(), call_id, - payload: ToolPayload::LocalShell { params }, + payload: ToolPayload::LocalShell { + params, + is_user_shell_command: false, + }, })) } }