From fe982f5fb65959b8fdbc3c43a1f6d62374ff2666 Mon Sep 17 00:00:00 2001 From: Charles Cunningham Date: Fri, 13 Mar 2026 11:25:15 -0700 Subject: [PATCH] Gate additional-permission guidance on exec approvals only Co-authored-by: Codex --- codex-rs/core/src/model_visible_fragments.rs | 5 +-- .../core/tests/suite/permissions_messages.rs | 42 +++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/codex-rs/core/src/model_visible_fragments.rs b/codex-rs/core/src/model_visible_fragments.rs index 131c3507b9..18e26c0b26 100644 --- a/codex-rs/core/src/model_visible_fragments.rs +++ b/codex-rs/core/src/model_visible_fragments.rs @@ -224,10 +224,7 @@ impl ModelVisibleContextFragment for PermissionsUpdateFragment { &turn_context.cwd, turn_context .features - .enabled(Feature::ExecPermissionApprovals) - || turn_context - .features - .enabled(Feature::RequestPermissionsTool), + .enabled(Feature::ExecPermissionApprovals), ), }) } diff --git a/codex-rs/core/tests/suite/permissions_messages.rs b/codex-rs/core/tests/suite/permissions_messages.rs index 016473a56c..a2428090a8 100644 --- a/codex-rs/core/tests/suite/permissions_messages.rs +++ b/codex-rs/core/tests/suite/permissions_messages.rs @@ -122,6 +122,48 @@ async fn permissions_message_mentions_additional_permissions_for_legacy_exec_flo Ok(()) } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn permissions_message_omits_additional_permissions_without_exec_approvals() -> Result<()> { + skip_if_no_network!(Ok(())); + + let server = start_mock_server().await; + let req = mount_sse_once( + &server, + sse(vec![ev_response_created("resp-1"), ev_completed("resp-1")]), + ) + .await; + + let mut builder = test_codex().with_config(move |config| { + config.permissions.approval_policy = Constrained::allow_any(AskForApproval::OnRequest); + config + .features + .enable(Feature::RequestPermissionsTool) + .expect("test config should allow feature update"); + }); + let test = builder.build(&server).await?; + + test.codex + .submit(Op::UserInput { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + final_output_json_schema: None, + }) + .await?; + wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; + + let request = req.single_request(); + let body = request.body_json(); + let input = body["input"].as_array().expect("input array"); + let permissions = permissions_texts(input); + assert_eq!(permissions.len(), 1); + assert!(!permissions[0].contains("with_additional_permissions")); + assert!(!permissions[0].contains("additional_permissions")); + + Ok(()) +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn permissions_message_added_on_override_change() -> Result<()> { skip_if_no_network!(Ok(()));