From 7f571396c8819d7f4c4486ed1e967e40a2c9ffae Mon Sep 17 00:00:00 2001 From: viyatb-oai Date: Fri, 13 Mar 2026 20:03:49 -0700 Subject: [PATCH] fix: sync split sandbox policies for spawned subagents (#14650) ## Summary - reapply the live split filesystem and network sandbox policies when building spawned subagent configs - keep spawned child sessions aligned with the parent turn after role-layer config reloads - add regression coverage for both config construction and spawned child-turn inheritance --- .../core/src/tools/handlers/multi_agents.rs | 2 ++ .../src/tools/handlers/multi_agents_tests.rs | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/codex-rs/core/src/tools/handlers/multi_agents.rs b/codex-rs/core/src/tools/handlers/multi_agents.rs index 01537f7f4..75ce10378 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents.rs @@ -307,6 +307,8 @@ fn apply_spawn_agent_runtime_overrides( .map_err(|err| { FunctionCallError::RespondToModel(format!("sandbox_policy is invalid: {err}")) })?; + config.permissions.file_system_sandbox_policy = turn.file_system_sandbox_policy.clone(); + config.permissions.network_sandbox_policy = turn.network_sandbox_policy; Ok(()) } diff --git a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs index 6720a6df3..1a46c7de5 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs @@ -8,6 +8,8 @@ use crate::config::DEFAULT_AGENT_MAX_DEPTH; use crate::config::types::ShellEnvironmentPolicy; use crate::function_tool::FunctionCallError; use crate::protocol::AskForApproval; +use crate::protocol::FileSystemSandboxPolicy; +use crate::protocol::NetworkSandboxPolicy; use crate::protocol::Op; use crate::protocol::SandboxPolicy; use crate::protocol::SessionSource; @@ -257,12 +259,17 @@ async fn spawn_agent_reapplies_runtime_sandbox_after_role_config() { &turn.config.permissions.sandbox_policy, turn.config.permissions.sandbox_policy.get().clone(), ); + let expected_file_system_sandbox_policy = + FileSystemSandboxPolicy::from_legacy_sandbox_policy(&expected_sandbox, &turn.cwd); + let expected_network_sandbox_policy = NetworkSandboxPolicy::from(&expected_sandbox); turn.approval_policy .set(AskForApproval::OnRequest) .expect("approval policy should be set"); turn.sandbox_policy .set(expected_sandbox.clone()) .expect("sandbox policy should be set"); + turn.file_system_sandbox_policy = expected_file_system_sandbox_policy.clone(); + turn.network_sandbox_policy = expected_network_sandbox_policy; assert_ne!( expected_sandbox, turn.config.permissions.sandbox_policy.get().clone(), @@ -301,6 +308,19 @@ async fn spawn_agent_reapplies_runtime_sandbox_after_role_config() { .await; assert_eq!(snapshot.sandbox_policy, expected_sandbox); assert_eq!(snapshot.approval_policy, AskForApproval::OnRequest); + let child_thread = manager + .get_thread(agent_id) + .await + .expect("spawned agent thread should exist"); + let child_turn = child_thread.codex.session.new_default_turn().await; + assert_eq!( + child_turn.file_system_sandbox_policy, + expected_file_system_sandbox_policy + ); + assert_eq!( + child_turn.network_sandbox_policy, + expected_network_sandbox_policy + ); } #[tokio::test] @@ -1020,9 +1040,14 @@ async fn build_agent_spawn_config_uses_turn_context_values() { &turn.config.permissions.sandbox_policy, turn.config.permissions.sandbox_policy.get().clone(), ); + let file_system_sandbox_policy = + FileSystemSandboxPolicy::from_legacy_sandbox_policy(&sandbox_policy, &turn.cwd); + let network_sandbox_policy = NetworkSandboxPolicy::from(&sandbox_policy); turn.sandbox_policy .set(sandbox_policy) .expect("sandbox policy set"); + turn.file_system_sandbox_policy = file_system_sandbox_policy.clone(); + turn.network_sandbox_policy = network_sandbox_policy; turn.approval_policy .set(AskForApproval::OnRequest) .expect("approval policy set"); @@ -1049,6 +1074,8 @@ async fn build_agent_spawn_config_uses_turn_context_values() { .sandbox_policy .set(turn.sandbox_policy.get().clone()) .expect("sandbox policy set"); + expected.permissions.file_system_sandbox_policy = file_system_sandbox_policy; + expected.permissions.network_sandbox_policy = network_sandbox_policy; assert_eq!(config, expected); }