diff --git a/codex-rs/common/src/approval_mode_cli_arg.rs b/codex-rs/common/src/approval_mode_cli_arg.rs index 94bd8e89..66717cd2 100644 --- a/codex-rs/common/src/approval_mode_cli_arg.rs +++ b/codex-rs/common/src/approval_mode_cli_arg.rs @@ -8,16 +8,16 @@ use codex_core::protocol::AskForApproval; #[derive(Clone, Copy, Debug, ValueEnum)] #[value(rename_all = "kebab-case")] pub enum ApprovalModeCliArg { + /// Only run "trusted" commands (e.g. ls, cat, sed) without asking for user + /// approval. Will escalate to the user if the model proposes a command that + /// is not in the "trusted" set. + Untrusted, + /// Run all commands without asking for user approval. /// Only asks for approval if a command fails to execute, in which case it /// will escalate to the user to ask for un-sandboxed execution. OnFailure, - /// Only run "known safe" commands (e.g. ls, cat, sed) without - /// asking for user approval. Will escalate to the user if the model - /// proposes a command that is not allow-listed. - UnlessAllowListed, - /// Never ask for user approval /// Execution failures are immediately returned to the model. Never, @@ -26,8 +26,8 @@ pub enum ApprovalModeCliArg { impl From for AskForApproval { fn from(value: ApprovalModeCliArg) -> Self { match value { + ApprovalModeCliArg::Untrusted => AskForApproval::UnlessAllowListed, ApprovalModeCliArg::OnFailure => AskForApproval::OnFailure, - ApprovalModeCliArg::UnlessAllowListed => AskForApproval::UnlessAllowListed, ApprovalModeCliArg::Never => AskForApproval::Never, } } diff --git a/codex-rs/config.md b/codex-rs/config.md index 0da42b9a..14d5fd22 100644 --- a/codex-rs/config.md +++ b/codex-rs/config.md @@ -80,8 +80,13 @@ wire_api = "chat" Determines when the user should be prompted to approve whether Codex can execute a command: ```toml -# This is analogous to --suggest in the TypeScript Codex CLI -approval_policy = "unless-allow-listed" +# Codex has hardcoded logic that defines a set of "trusted" commands. +# Setting the approval_policy to `untrusted` means that Codex will prompt the +# user before running a command not in the "trusted" set. +# +# See https://github.com/openai/codex/issues/1260 for the plan to enable +# end-users to define their own trusted commands. +approval_policy = "untrusted" ``` ```toml diff --git a/codex-rs/core/src/config.rs b/codex-rs/core/src/config.rs index bea37e90..d960417c 100644 --- a/codex-rs/core/src/config.rs +++ b/codex-rs/core/src/config.rs @@ -586,7 +586,7 @@ writable_roots = [ fn create_test_fixture() -> std::io::Result { let toml = r#" model = "o3" -approval_policy = "unless-allow-listed" +approval_policy = "untrusted" disable_response_storage = false # Can be used to determine which profile to use if not specified by diff --git a/codex-rs/core/src/protocol.rs b/codex-rs/core/src/protocol.rs index 42cf9299..7533ddf8 100644 --- a/codex-rs/core/src/protocol.rs +++ b/codex-rs/core/src/protocol.rs @@ -110,22 +110,18 @@ pub enum Op { GetHistoryEntryRequest { offset: usize, log_id: u64 }, } -/// Determines how liberally commands are auto‑approved by the system. +/// Determines the conditions under which the user is consulted to approve +/// running the command proposed by Codex. #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub enum AskForApproval { - /// Under this policy, only “known safe” commands—as determined by + /// Under this policy, only "known safe" commands—as determined by /// `is_safe_command()`—that **only read files** are auto‑approved. /// Everything else will ask the user to approve. #[default] + #[serde(rename = "untrusted")] UnlessAllowListed, - /// In addition to everything allowed by **`Suggest`**, commands that - /// *write* to files **within the user’s approved list of writable paths** - /// are also auto‑approved. - /// TODO(ragona): fix - AutoEdit, - /// *All* commands are auto‑approved, but they are expected to run inside a /// sandbox where network access is disabled and writes are confined to a /// specific set of paths. If the command fails, it will be escalated to diff --git a/codex-rs/core/src/safety.rs b/codex-rs/core/src/safety.rs index 8417bf0c..a93316e3 100644 --- a/codex-rs/core/src/safety.rs +++ b/codex-rs/core/src/safety.rs @@ -31,7 +31,7 @@ pub fn assess_patch_safety( } match policy { - AskForApproval::OnFailure | AskForApproval::AutoEdit | AskForApproval::Never => { + AskForApproval::OnFailure | AskForApproval::Never => { // Continue to see if this can be auto-approved. } // TODO(ragona): I'm not sure this is actually correct? I believe in this case diff --git a/codex-rs/mcp-server/src/codex_tool_config.rs b/codex-rs/mcp-server/src/codex_tool_config.rs index 0afefc15..4baaa37c 100644 --- a/codex-rs/mcp-server/src/codex_tool_config.rs +++ b/codex-rs/mcp-server/src/codex_tool_config.rs @@ -47,8 +47,7 @@ pub(crate) struct CodexToolCallParam { #[derive(Debug, Clone, Deserialize, JsonSchema)] #[serde(rename_all = "kebab-case")] pub(crate) enum CodexToolCallApprovalPolicy { - AutoEdit, - UnlessAllowListed, + Untrusted, OnFailure, Never, } @@ -56,8 +55,7 @@ pub(crate) enum CodexToolCallApprovalPolicy { impl From for AskForApproval { fn from(value: CodexToolCallApprovalPolicy) -> Self { match value { - CodexToolCallApprovalPolicy::AutoEdit => AskForApproval::AutoEdit, - CodexToolCallApprovalPolicy::UnlessAllowListed => AskForApproval::UnlessAllowListed, + CodexToolCallApprovalPolicy::Untrusted => AskForApproval::UnlessAllowListed, CodexToolCallApprovalPolicy::OnFailure => AskForApproval::OnFailure, CodexToolCallApprovalPolicy::Never => AskForApproval::Never, } @@ -164,8 +162,7 @@ mod tests { "approval-policy": { "description": "Execution approval policy expressed as the kebab-case variant name (`unless-allow-listed`, `auto-edit`, `on-failure`, `never`).", "enum": [ - "auto-edit", - "unless-allow-listed", + "untrusted", "on-failure", "never" ],