Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion codex-rs/app-server/src/codex_message_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ use codex_core::protocol::ReviewRequest;
use codex_core::protocol::ReviewTarget as CoreReviewTarget;
use codex_core::protocol::SessionConfiguredEvent;
use codex_core::read_head_for_summary;
use codex_core::sandboxing::SandboxPermissions;
use codex_feedback::CodexFeedback;
use codex_login::ServerOptions as LoginServerOptions;
use codex_login::ShutdownHandle;
Expand Down Expand Up @@ -1191,7 +1192,7 @@ impl CodexMessageProcessor {
cwd,
expiration: timeout_ms.into(),
env,
with_escalated_permissions: None,
sandbox_permissions: SandboxPermissions::UseDefault,
justification: None,
arg0: None,
};
Expand Down
6 changes: 3 additions & 3 deletions codex-rs/core/gpt-5.1-codex-max_prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ When you are running with `approval_policy == on-request`, and sandboxing enable
- You need to run a command that writes to a directory that requires it (e.g. running tests that write to /var)
- You need to run a GUI app (e.g., open/xdg-open/osascript) to open browsers or files.
- You are running sandboxed and need to run a command that requires network access (e.g. installing packages)
- If you run a command that is important to solving the user's query, but it fails because of sandboxing, rerun the command with approval. ALWAYS proceed to use the `with_escalated_permissions` and `justification` parameters - do not message the user before requesting approval for the command.
- If you run a command that is important to solving the user's query, but it fails because of sandboxing, rerun the command with approval. ALWAYS proceed to use the `sandbox_permissions` and `justification` parameters - do not message the user before requesting approval for the command.
- You are about to take a potentially destructive action such as an `rm` or `git reset` that the user did not explicitly ask for
- (for all of these, you should weigh alternative paths that do not require approval)

Expand All @@ -59,8 +59,8 @@ You will be told what filesystem sandboxing, network sandboxing, and approval mo
Although they introduce friction to the user because your work is paused until the user responds, you should leverage them when necessary to accomplish important work. If the completing the task requires escalated permissions, Do not let these settings or the sandbox deter you from attempting to accomplish the user's task unless it is set to "never", in which case never ask for approvals.

When requesting approval to execute a command that will require escalated privileges:
- Provide the `with_escalated_permissions` parameter with the boolean value true
- Include a short, 1 sentence explanation for why you need to enable `with_escalated_permissions` in the justification parameter
- Provide the `sandbox_permissions` parameter with the value `"require_escalated"`
- Include a short, 1 sentence explanation for why you need escalated permissions in the justification parameter

## Special user requests

Expand Down
6 changes: 3 additions & 3 deletions codex-rs/core/gpt_5_1_prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ When you are running with `approval_policy == on-request`, and sandboxing enable
- You need to run a command that writes to a directory that requires it (e.g. running tests that write to /var)
- You need to run a GUI app (e.g., open/xdg-open/osascript) to open browsers or files.
- You are running sandboxed and need to run a command that requires network access (e.g. installing packages)
- If you run a command that is important to solving the user's query, but it fails because of sandboxing, rerun the command with approval. ALWAYS proceed to use the `with_escalated_permissions` and `justification` parameters. Within this harness, prefer requesting approval via the tool over asking in natural language.
- If you run a command that is important to solving the user's query, but it fails because of sandboxing, rerun the command with approval. ALWAYS proceed to use the `sandbox_permissions` and `justification` parameters. Within this harness, prefer requesting approval via the tool over asking in natural language.
- You are about to take a potentially destructive action such as an `rm` or `git reset` that the user did not explicitly ask for
- (for all of these, you should weigh alternative paths that do not require approval)

Expand All @@ -193,8 +193,8 @@ You will be told what filesystem sandboxing, network sandboxing, and approval mo
Although they introduce friction to the user because your work is paused until the user responds, you should leverage them when necessary to accomplish important work. If the completing the task requires escalated permissions, Do not let these settings or the sandbox deter you from attempting to accomplish the user's task unless it is set to "never", in which case never ask for approvals.

When requesting approval to execute a command that will require escalated privileges:
- Provide the `with_escalated_permissions` parameter with the boolean value true
- Include a short, 1 sentence explanation for why you need to enable `with_escalated_permissions` in the justification parameter
- Provide the `sandbox_permissions` parameter with the value `"require_escalated"`
- Include a short, 1 sentence explanation for why you need escalated permissions in the justification parameter

## Validating your work

Expand Down
6 changes: 3 additions & 3 deletions codex-rs/core/gpt_5_codex_prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ When you are running with `approval_policy == on-request`, and sandboxing enable
- You need to run a command that writes to a directory that requires it (e.g. running tests that write to /var)
- You need to run a GUI app (e.g., open/xdg-open/osascript) to open browsers or files.
- You are running sandboxed and need to run a command that requires network access (e.g. installing packages)
- If you run a command that is important to solving the user's query, but it fails because of sandboxing, rerun the command with approval. ALWAYS proceed to use the `with_escalated_permissions` and `justification` parameters - do not message the user before requesting approval for the command.
- If you run a command that is important to solving the user's query, but it fails because of sandboxing, rerun the command with approval. ALWAYS proceed to use the `sandbox_permissions` and `justification` parameters - do not message the user before requesting approval for the command.
- You are about to take a potentially destructive action such as an `rm` or `git reset` that the user did not explicitly ask for
- (for all of these, you should weigh alternative paths that do not require approval)

Expand All @@ -59,8 +59,8 @@ You will be told what filesystem sandboxing, network sandboxing, and approval mo
Although they introduce friction to the user because your work is paused until the user responds, you should leverage them when necessary to accomplish important work. If the completing the task requires escalated permissions, Do not let these settings or the sandbox deter you from attempting to accomplish the user's task unless it is set to "never", in which case never ask for approvals.

When requesting approval to execute a command that will require escalated privileges:
- Provide the `with_escalated_permissions` parameter with the boolean value true
- Include a short, 1 sentence explanation for why you need to enable `with_escalated_permissions` in the justification parameter
- Provide the `sandbox_permissions` parameter with the value `"require_escalated"`
- Include a short, 1 sentence explanation for why you need escalated permissions in the justification parameter

## Special user requests

Expand Down
13 changes: 8 additions & 5 deletions codex-rs/core/src/codex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3325,6 +3325,7 @@ mod tests {
use crate::exec::ExecParams;
use crate::protocol::AskForApproval;
use crate::protocol::SandboxPolicy;
use crate::sandboxing::SandboxPermissions;
use crate::turn_diff_tracker::TurnDiffTracker;
use std::collections::HashMap;

Expand All @@ -3335,6 +3336,7 @@ mod tests {
let mut turn_context = Arc::new(turn_context_raw);

let timeout_ms = 1000;
let sandbox_permissions = SandboxPermissions::RequireEscalated;
let params = ExecParams {
command: if cfg!(windows) {
vec![
Expand All @@ -3352,13 +3354,13 @@ mod tests {
cwd: turn_context.cwd.clone(),
expiration: timeout_ms.into(),
env: HashMap::new(),
with_escalated_permissions: Some(true),
sandbox_permissions,
justification: Some("test".to_string()),
arg0: None,
};

let params2 = ExecParams {
with_escalated_permissions: Some(false),
sandbox_permissions: SandboxPermissions::UseDefault,
command: params.command.clone(),
cwd: params.cwd.clone(),
expiration: timeout_ms.into(),
Expand All @@ -3385,7 +3387,7 @@ mod tests {
"command": params.command.clone(),
"workdir": Some(turn_context.cwd.to_string_lossy().to_string()),
"timeout_ms": params.expiration.timeout_ms(),
"with_escalated_permissions": params.with_escalated_permissions,
"sandbox_permissions": params.sandbox_permissions,
"justification": params.justification.clone(),
})
.to_string(),
Expand Down Expand Up @@ -3422,7 +3424,7 @@ mod tests {
"command": params2.command.clone(),
"workdir": Some(turn_context.cwd.to_string_lossy().to_string()),
"timeout_ms": params2.expiration.timeout_ms(),
"with_escalated_permissions": params2.with_escalated_permissions,
"sandbox_permissions": params2.sandbox_permissions,
"justification": params2.justification.clone(),
})
.to_string(),
Expand Down Expand Up @@ -3455,6 +3457,7 @@ mod tests {
#[tokio::test]
async fn unified_exec_rejects_escalated_permissions_when_policy_not_on_request() {
use crate::protocol::AskForApproval;
use crate::sandboxing::SandboxPermissions;
use crate::turn_diff_tracker::TurnDiffTracker;

let (session, mut turn_context_raw) = make_session_and_context();
Expand All @@ -3474,7 +3477,7 @@ mod tests {
payload: ToolPayload::Function {
arguments: serde_json::json!({
"cmd": "echo hi",
"with_escalated_permissions": true,
"sandbox_permissions": SandboxPermissions::RequireEscalated,
"justification": "need unsandboxed execution",
})
.to_string(),
Expand Down
15 changes: 8 additions & 7 deletions codex-rs/core/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use crate::protocol::SandboxPolicy;
use crate::sandboxing::CommandSpec;
use crate::sandboxing::ExecEnv;
use crate::sandboxing::SandboxManager;
use crate::sandboxing::SandboxPermissions;
use crate::spawn::StdioPolicy;
use crate::spawn::spawn_child_async;
use crate::text_encoding::bytes_to_string_smart;
Expand Down Expand Up @@ -55,7 +56,7 @@ pub struct ExecParams {
pub cwd: PathBuf,
pub expiration: ExecExpiration,
pub env: HashMap<String, String>,
pub with_escalated_permissions: Option<bool>,
pub sandbox_permissions: SandboxPermissions,
pub justification: Option<String>,
pub arg0: Option<String>,
}
Expand Down Expand Up @@ -144,7 +145,7 @@ pub async fn process_exec_tool_call(
cwd,
expiration,
env,
with_escalated_permissions,
sandbox_permissions,
justification,
arg0: _,
} = params;
Expand All @@ -162,7 +163,7 @@ pub async fn process_exec_tool_call(
cwd,
env,
expiration,
with_escalated_permissions,
sandbox_permissions,
justification,
};

Expand Down Expand Up @@ -192,7 +193,7 @@ pub(crate) async fn execute_exec_env(
env,
expiration,
sandbox,
with_escalated_permissions,
sandbox_permissions,
justification,
arg0,
} = env;
Expand All @@ -202,7 +203,7 @@ pub(crate) async fn execute_exec_env(
cwd,
expiration,
env,
with_escalated_permissions,
sandbox_permissions,
justification,
arg0,
};
Expand Down Expand Up @@ -857,7 +858,7 @@ mod tests {
cwd: std::env::current_dir()?,
expiration: 500.into(),
env,
with_escalated_permissions: None,
sandbox_permissions: SandboxPermissions::UseDefault,
justification: None,
arg0: None,
};
Expand Down Expand Up @@ -902,7 +903,7 @@ mod tests {
cwd: cwd.clone(),
expiration: ExecExpiration::Cancellation(cancel_token),
env,
with_escalated_permissions: None,
sandbox_permissions: SandboxPermissions::UseDefault,
justification: None,
arg0: None,
};
Expand Down
29 changes: 4 additions & 25 deletions codex-rs/core/src/sandboxing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,40 +23,19 @@ use crate::seatbelt::create_seatbelt_command_args;
use crate::spawn::CODEX_SANDBOX_ENV_VAR;
use crate::spawn::CODEX_SANDBOX_NETWORK_DISABLED_ENV_VAR;
use crate::tools::sandboxing::SandboxablePreference;
pub use codex_protocol::models::SandboxPermissions;
use std::collections::HashMap;
use std::path::Path;
use std::path::PathBuf;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SandboxPermissions {
UseDefault,
RequireEscalated,
}

impl SandboxPermissions {
pub fn requires_escalated_permissions(self) -> bool {
matches!(self, SandboxPermissions::RequireEscalated)
}
}

impl From<bool> for SandboxPermissions {
fn from(with_escalated_permissions: bool) -> Self {
if with_escalated_permissions {
SandboxPermissions::RequireEscalated
} else {
SandboxPermissions::UseDefault
}
}
}

#[derive(Debug)]
pub struct CommandSpec {
pub program: String,
pub args: Vec<String>,
pub cwd: PathBuf,
pub env: HashMap<String, String>,
pub expiration: ExecExpiration,
pub with_escalated_permissions: Option<bool>,
pub sandbox_permissions: SandboxPermissions,
pub justification: Option<String>,
}

Expand All @@ -67,7 +46,7 @@ pub struct ExecEnv {
pub env: HashMap<String, String>,
pub expiration: ExecExpiration,
pub sandbox: SandboxType,
pub with_escalated_permissions: Option<bool>,
pub sandbox_permissions: SandboxPermissions,
pub justification: Option<String>,
pub arg0: Option<String>,
}
Expand Down Expand Up @@ -181,7 +160,7 @@ impl SandboxManager {
env,
expiration: spec.expiration,
sandbox,
with_escalated_permissions: spec.with_escalated_permissions,
sandbox_permissions: spec.sandbox_permissions,
justification: spec.justification,
arg0: arg0_override,
})
Expand Down
3 changes: 2 additions & 1 deletion codex-rs/core/src/tasks/user_shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use crate::protocol::ExecCommandSource;
use crate::protocol::SandboxPolicy;
use crate::protocol::TaskStartedEvent;
use crate::sandboxing::ExecEnv;
use crate::sandboxing::SandboxPermissions;
use crate::state::TaskKind;
use crate::tools::format_exec_output_str;
use crate::user_shell_command::user_shell_command_record_item;
Expand Down Expand Up @@ -100,7 +101,7 @@ impl SessionTask for UserShellCommandTask {
// should use that instead of an "arbitrarily large" timeout here.
expiration: USER_SHELL_TIMEOUT_MS.into(),
sandbox: SandboxType::None,
with_escalated_permissions: None,
sandbox_permissions: SandboxPermissions::UseDefault,
justification: None,
arg0: None,
};
Expand Down
23 changes: 11 additions & 12 deletions codex-rs/core/src/tools/handlers/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use crate::exec_policy::create_exec_approval_requirement_for_command;
use crate::function_tool::FunctionCallError;
use crate::is_safe_command::is_known_safe_command;
use crate::protocol::ExecCommandSource;
use crate::sandboxing::SandboxPermissions;
use crate::tools::context::ToolInvocation;
use crate::tools::context::ToolOutput;
use crate::tools::context::ToolPayload;
Expand All @@ -35,7 +34,7 @@ impl ShellHandler {
cwd: turn_context.resolve_path(params.workdir.clone()),
expiration: params.timeout_ms.into(),
env: create_env(&turn_context.shell_environment_policy),
with_escalated_permissions: params.with_escalated_permissions,
sandbox_permissions: params.sandbox_permissions.unwrap_or_default(),
justification: params.justification,
arg0: None,
}
Expand All @@ -56,7 +55,7 @@ impl ShellCommandHandler {
cwd: turn_context.resolve_path(params.workdir.clone()),
expiration: params.timeout_ms.into(),
env: create_env(&turn_context.shell_environment_policy),
with_escalated_permissions: params.with_escalated_permissions,
sandbox_permissions: params.sandbox_permissions.unwrap_or_default(),
justification: params.justification,
arg0: None,
}
Expand Down Expand Up @@ -206,7 +205,9 @@ impl ShellHandler {
freeform: bool,
) -> Result<ToolOutput, FunctionCallError> {
// Approval policy guard for explicit escalation in non-OnRequest modes.
if exec_params.with_escalated_permissions.unwrap_or(false)
if exec_params
.sandbox_permissions
.requires_escalated_permissions()
&& !matches!(
turn.approval_policy,
codex_protocol::protocol::AskForApproval::OnRequest
Expand Down Expand Up @@ -251,7 +252,7 @@ impl ShellHandler {
&exec_params.command,
turn.approval_policy,
&turn.sandbox_policy,
SandboxPermissions::from(exec_params.with_escalated_permissions.unwrap_or(false)),
exec_params.sandbox_permissions,
)
.await;

Expand All @@ -260,7 +261,7 @@ impl ShellHandler {
cwd: exec_params.cwd.clone(),
timeout_ms: exec_params.expiration.timeout_ms(),
env: exec_params.env.clone(),
with_escalated_permissions: exec_params.with_escalated_permissions,
sandbox_permissions: exec_params.sandbox_permissions,
justification: exec_params.justification.clone(),
exec_approval_requirement,
};
Expand Down Expand Up @@ -295,6 +296,7 @@ mod tests {
use crate::codex::make_session_and_context;
use crate::exec_env::create_env;
use crate::is_safe_command::is_known_safe_command;
use crate::sandboxing::SandboxPermissions;
use crate::shell::Shell;
use crate::shell::ShellType;
use crate::tools::handlers::ShellCommandHandler;
Expand Down Expand Up @@ -343,7 +345,7 @@ mod tests {
let workdir = Some("subdir".to_string());
let login = None;
let timeout_ms = Some(1234);
let with_escalated_permissions = Some(true);
let sandbox_permissions = SandboxPermissions::RequireEscalated;
let justification = Some("because tests".to_string());

let expected_command = session.user_shell().derive_exec_args(&command, true);
Expand All @@ -355,7 +357,7 @@ mod tests {
workdir,
login,
timeout_ms,
with_escalated_permissions,
sandbox_permissions: Some(sandbox_permissions),
justification: justification.clone(),
};

Expand All @@ -366,10 +368,7 @@ mod tests {
assert_eq!(exec_params.cwd, expected_cwd);
assert_eq!(exec_params.env, expected_env);
assert_eq!(exec_params.expiration.timeout_ms(), timeout_ms);
assert_eq!(
exec_params.with_escalated_permissions,
with_escalated_permissions
);
assert_eq!(exec_params.sandbox_permissions, sandbox_permissions);
assert_eq!(exec_params.justification, justification);
assert_eq!(exec_params.arg0, None);
}
Expand Down
Loading
Loading