@@ -43,7 +43,6 @@ use crate::state::TaskKind;
4343use crate :: tasks:: SessionTask ;
4444use crate :: tasks:: SessionTaskContext ;
4545use crate :: tools:: ToolRouter ;
46- use crate :: tools:: context:: FunctionToolOutput ;
4746use crate :: tools:: context:: ToolInvocation ;
4847use crate :: tools:: context:: ToolPayload ;
4948use crate :: tools:: handlers:: ShellHandler ;
@@ -120,12 +119,6 @@ use std::time::Duration as StdDuration;
120119#[ path = "codex_tests_guardian.rs" ]
121120mod guardian_tests;
122121
123- use codex_protocol:: models:: function_call_output_content_items_to_text;
124-
125- fn expect_text_tool_output ( output : & FunctionToolOutput ) -> String {
126- function_call_output_content_items_to_text ( & output. body ) . unwrap_or_default ( )
127- }
128-
129122struct InstructionsTestCase {
130123 slug : & ' static str ,
131124 expects_apply_patch_instructions : bool ,
@@ -5348,7 +5341,9 @@ async fn sample_rollout(
53485341#[ tokio:: test]
53495342async fn rejects_escalated_permissions_when_policy_not_on_request ( ) {
53505343 use crate :: exec:: ExecParams ;
5344+ use crate :: exec_policy:: ExecApprovalRequest ;
53515345 use crate :: sandboxing:: SandboxPermissions ;
5346+ use crate :: tools:: sandboxing:: ExecApprovalRequirement ;
53525347 use crate :: turn_diff_tracker:: TurnDiffTracker ;
53535348 use codex_protocol:: protocol:: AskForApproval ;
53545349 use codex_protocol:: protocol:: SandboxPolicy ;
@@ -5394,23 +5389,6 @@ async fn rejects_escalated_permissions_when_policy_not_on_request() {
53945389 arg0 : None ,
53955390 } ;
53965391
5397- let params2 = ExecParams {
5398- sandbox_permissions : SandboxPermissions :: UseDefault ,
5399- command : params. command . clone ( ) ,
5400- cwd : params. cwd . clone ( ) ,
5401- expiration : timeout_ms. into ( ) ,
5402- capture_policy : ExecCapturePolicy :: ShellTool ,
5403- env : HashMap :: new ( ) ,
5404- network : None ,
5405- windows_sandbox_level : turn_context. windows_sandbox_level ,
5406- windows_sandbox_private_desktop : turn_context
5407- . config
5408- . permissions
5409- . windows_sandbox_private_desktop ,
5410- justification : params. justification . clone ( ) ,
5411- arg0 : None ,
5412- } ;
5413-
54145392 let turn_diff_tracker = Arc :: new ( tokio:: sync:: Mutex :: new ( TurnDiffTracker :: new ( ) ) ) ;
54155393
54165394 let tool_name = "shell" ;
@@ -5448,9 +5426,11 @@ async fn rejects_escalated_permissions_when_policy_not_on_request() {
54485426 ) ;
54495427
54505428 pretty_assertions:: assert_eq!( output, expected) ;
5429+ pretty_assertions:: assert_eq!( session. granted_turn_permissions( ) . await , None ) ;
54515430
5452- // Now retry the same command WITHOUT escalated permissions; should succeed.
5453- // Force DangerFullAccess to avoid platform sandbox dependencies in tests.
5431+ // The rejection should not poison the non-escalated path for the same
5432+ // command. Force DangerFullAccess so this check stays focused on approval
5433+ // policy rather than platform-specific sandbox behavior.
54545434 let turn_context_mut = Arc :: get_mut ( & mut turn_context) . expect ( "unique turn context Arc" ) ;
54555435 turn_context_mut
54565436 . sandbox_policy
@@ -5461,45 +5441,22 @@ async fn rejects_escalated_permissions_when_policy_not_on_request() {
54615441 turn_context_mut. network_sandbox_policy =
54625442 NetworkSandboxPolicy :: from ( turn_context_mut. sandbox_policy . get ( ) ) ;
54635443
5464- let resp2 = handler
5465- . handle ( ToolInvocation {
5466- session : Arc :: clone ( & session) ,
5467- turn : Arc :: clone ( & turn_context) ,
5468- tracker : Arc :: clone ( & turn_diff_tracker) ,
5469- call_id : "test-call-2" . to_string ( ) ,
5470- tool_name : tool_name. to_string ( ) ,
5471- tool_namespace : None ,
5472- payload : ToolPayload :: Function {
5473- arguments : serde_json:: json!( {
5474- "command" : params2. command. clone( ) ,
5475- "workdir" : Some ( turn_context. cwd. to_string_lossy( ) . to_string( ) ) ,
5476- "timeout_ms" : params2. expiration. timeout_ms( ) ,
5477- "sandbox_permissions" : params2. sandbox_permissions,
5478- "justification" : params2. justification. clone( ) ,
5479- } )
5480- . to_string ( ) ,
5481- } ,
5444+ let exec_approval_requirement = session
5445+ . services
5446+ . exec_policy
5447+ . create_exec_approval_requirement_for_command ( ExecApprovalRequest {
5448+ command : & params. command ,
5449+ approval_policy : turn_context. approval_policy . value ( ) ,
5450+ sandbox_policy : turn_context. sandbox_policy . get ( ) ,
5451+ file_system_sandbox_policy : & turn_context. file_system_sandbox_policy ,
5452+ sandbox_permissions : SandboxPermissions :: UseDefault ,
5453+ prefix_rule : None ,
54825454 } )
54835455 . await ;
5484-
5485- let output = expect_text_tool_output ( & resp2. expect ( "expected Ok result" ) ) ;
5486-
5487- #[ derive( Deserialize , PartialEq , Eq , Debug ) ]
5488- struct ResponseExecMetadata {
5489- exit_code : i32 ,
5490- }
5491-
5492- #[ derive( Deserialize ) ]
5493- struct ResponseExecOutput {
5494- output : String ,
5495- metadata : ResponseExecMetadata ,
5496- }
5497-
5498- let exec_output: ResponseExecOutput =
5499- serde_json:: from_str ( & output) . expect ( "valid exec output json" ) ;
5500-
5501- pretty_assertions:: assert_eq!( exec_output. metadata, ResponseExecMetadata { exit_code: 0 } ) ;
5502- assert ! ( exec_output. output. contains( "hi" ) ) ;
5456+ assert ! ( matches!(
5457+ exec_approval_requirement,
5458+ ExecApprovalRequirement :: Skip { .. }
5459+ ) ) ;
55035460}
55045461#[ tokio:: test]
55055462async fn unified_exec_rejects_escalated_permissions_when_policy_not_on_request ( ) {
0 commit comments