diff --git a/codex-rs/windows-sandbox-rs/src/elevated/runner_client.rs b/codex-rs/windows-sandbox-rs/src/elevated/runner_client.rs index d313b6cfcc..a7b4049457 100644 --- a/codex-rs/windows-sandbox-rs/src/elevated/runner_client.rs +++ b/codex-rs/windows-sandbox-rs/src/elevated/runner_client.rs @@ -48,6 +48,12 @@ const RUNNER_SPAWN_READY_POLL_INTERVAL: Duration = Duration::from_millis(50); const RUNNER_ERROR_MODE_FLAGS: u32 = 0x0001 | 0x0002; const WAIT_OBJECT_0: u32 = 0; +fn runner_launch_cwd(codex_home: &Path) -> std::io::Result { + let launch_cwd = codex_home.join(".sandbox"); + std::fs::create_dir_all(&launch_cwd)?; + Ok(launch_cwd) +} + pub(crate) struct RunnerTransport { pipe_write: File, pipe_read: File, @@ -241,7 +247,8 @@ pub(crate) fn spawn_runner_transport( ); let mut cmdline_vec = to_wide(&runner_full_cmd); let exe_w = to_wide(&runner_cmdline); - let cwd_w = to_wide(cwd); + let launch_cwd = runner_launch_cwd(codex_home)?; + let cwd_w = to_wide(&launch_cwd); let user_w = to_wide(&sandbox_creds.username); let domain_w = to_wide("."); let password_w = to_wide(&sandbox_creds.password); @@ -392,3 +399,17 @@ fn wait_for_complete_frame(pipe_read: &File, timeout: Duration) -> Result<()> { std::thread::sleep(RUNNER_SPAWN_READY_POLL_INTERVAL); } } + +#[cfg(test)] +mod tests { + use super::runner_launch_cwd; + + #[test] + fn runner_launch_cwd_uses_local_sandbox_dir() { + let temp = tempfile::tempdir().expect("tempdir"); + let launch_cwd = runner_launch_cwd(temp.path()).expect("launch cwd"); + + assert_eq!(launch_cwd, temp.path().join(".sandbox")); + assert!(launch_cwd.is_dir()); + } +} diff --git a/codex-rs/windows-sandbox-rs/src/unified_exec/backends/elevated.rs b/codex-rs/windows-sandbox-rs/src/unified_exec/backends/elevated.rs index 4ee2b5fac5..eaeef86338 100644 --- a/codex-rs/windows-sandbox-rs/src/unified_exec/backends/elevated.rs +++ b/codex-rs/windows-sandbox-rs/src/unified_exec/backends/elevated.rs @@ -7,6 +7,7 @@ use crate::ipc_framed::EmptyPayload; use crate::ipc_framed::FramedMessage; use crate::ipc_framed::Message; use crate::ipc_framed::SpawnRequest; +use crate::path_normalization::resolve_sandbox_path; use crate::runner_client::spawn_runner_transport; use crate::spawn_prep::prepare_elevated_spawn_context; use anyhow::Result; @@ -40,12 +41,14 @@ pub(crate) async fn spawn_windows_sandbox_session_elevated( &command, )?; + let resolved_cwd = resolve_sandbox_path(cwd); + let resolved_policy_cwd = resolve_sandbox_path(sandbox_policy_cwd); let spawn_request = SpawnRequest { command: command.clone(), - cwd: cwd.to_path_buf(), + cwd: resolved_cwd, env: env_map.clone(), policy_json_or_preset: policy_json_or_preset.to_string(), - sandbox_policy_cwd: sandbox_policy_cwd.to_path_buf(), + sandbox_policy_cwd: resolved_policy_cwd, codex_home: elevated.common.sandbox_base.clone(), real_codex_home: codex_home.to_path_buf(), cap_sids: elevated.cap_sids.clone(),