From 8ec36fc336a7c1e7b6cc62068b99617b8edc715c Mon Sep 17 00:00:00 2001 From: David Wiesen Date: Mon, 6 Oct 2025 15:25:25 -0700 Subject: [PATCH] adds scaffold for windows sandbox with experimental flag. Does nothing yet. --- codex-rs/core/src/config.rs | 13 +++++++++++++ codex-rs/core/src/exec.rs | 12 ++++++++++-- codex-rs/core/src/safety.rs | 29 +++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/codex-rs/core/src/config.rs b/codex-rs/core/src/config.rs index 28ad84ba7a..42dfe71e06 100644 --- a/codex-rs/core/src/config.rs +++ b/codex-rs/core/src/config.rs @@ -26,6 +26,7 @@ use crate::model_provider_info::built_in_model_providers; use crate::openai_model_info::get_model_info; use crate::protocol::AskForApproval; use crate::protocol::SandboxPolicy; +use crate::safety::set_windows_sandbox_enabled; use anyhow::Context; use codex_app_server_protocol::Tools; use codex_app_server_protocol::UserSavedConfig; @@ -170,6 +171,9 @@ pub struct Config { /// When this program is invoked, arg0 will be set to `codex-linux-sandbox`. pub codex_linux_sandbox_exe: Option, + /// Enable the experimental Windows sandbox implementation. + pub experimental_windows_sandbox: bool, + /// Value to use for `reasoning.effort` when making a request using the /// Responses API. pub model_reasoning_effort: Option, @@ -751,6 +755,7 @@ pub struct ConfigToml { pub experimental_use_unified_exec_tool: Option, pub experimental_use_rmcp_client: Option, pub experimental_use_freeform_apply_patch: Option, + pub experimental_windows_sandbox: Option, pub projects: Option>, @@ -1008,6 +1013,8 @@ impl Config { .or(cfg.tools.as_ref().and_then(|t| t.view_image)) .unwrap_or(true); + let experimental_windows_sandbox = cfg.experimental_windows_sandbox.unwrap_or(false); + let model = model .or(config_profile.model) .or(cfg.model) @@ -1093,6 +1100,7 @@ impl Config { history, file_opener: cfg.file_opener.unwrap_or(UriBasedFileOpener::VsCode), codex_linux_sandbox_exe, + experimental_windows_sandbox, hide_agent_reasoning: cfg.hide_agent_reasoning.unwrap_or(false), show_raw_agent_reasoning: cfg @@ -1146,6 +1154,7 @@ impl Config { } }, }; + set_windows_sandbox_enabled(config.experimental_windows_sandbox); Ok(config) } @@ -1903,6 +1912,7 @@ model_verbosity = "high" history: History::default(), file_opener: UriBasedFileOpener::VsCode, codex_linux_sandbox_exe: None, + experimental_windows_sandbox: false, hide_agent_reasoning: false, show_raw_agent_reasoning: false, model_reasoning_effort: Some(ReasoningEffort::High), @@ -1965,6 +1975,7 @@ model_verbosity = "high" history: History::default(), file_opener: UriBasedFileOpener::VsCode, codex_linux_sandbox_exe: None, + experimental_windows_sandbox: false, hide_agent_reasoning: false, show_raw_agent_reasoning: false, model_reasoning_effort: None, @@ -2042,6 +2053,7 @@ model_verbosity = "high" history: History::default(), file_opener: UriBasedFileOpener::VsCode, codex_linux_sandbox_exe: None, + experimental_windows_sandbox: false, hide_agent_reasoning: false, show_raw_agent_reasoning: false, model_reasoning_effort: None, @@ -2105,6 +2117,7 @@ model_verbosity = "high" history: History::default(), file_opener: UriBasedFileOpener::VsCode, codex_linux_sandbox_exe: None, + experimental_windows_sandbox: false, hide_agent_reasoning: false, show_raw_agent_reasoning: false, model_reasoning_effort: Some(ReasoningEffort::High), diff --git a/codex-rs/core/src/exec.rs b/codex-rs/core/src/exec.rs index d84bbc9fcb..d768ca42d8 100644 --- a/codex-rs/core/src/exec.rs +++ b/codex-rs/core/src/exec.rs @@ -70,6 +70,9 @@ pub enum SandboxType { /// Only available on Linux. LinuxSeccomp, + + /// Only available on Windows. + WindowsAppContainer, } #[derive(Clone)] @@ -93,7 +96,9 @@ pub async fn process_exec_tool_call( let raw_output_result: std::result::Result = match sandbox_type { - SandboxType::None => exec(params, sandbox_policy, stdout_stream.clone()).await, + SandboxType::None | SandboxType::WindowsAppContainer => { + exec(params, sandbox_policy, stdout_stream.clone()).await + } SandboxType::MacosSeatbelt => { let ExecParams { command, @@ -198,7 +203,10 @@ pub async fn process_exec_tool_call( /// For now, we conservatively check for 'command not found' (exit code 127), /// and can add additional cases as necessary. fn is_likely_sandbox_denied(sandbox_type: SandboxType, exit_code: i32) -> bool { - if sandbox_type == SandboxType::None { + if matches!( + sandbox_type, + SandboxType::None | SandboxType::WindowsAppContainer + ) { return false; } diff --git a/codex-rs/core/src/safety.rs b/codex-rs/core/src/safety.rs index 0ed0f929ff..92b348d5e0 100644 --- a/codex-rs/core/src/safety.rs +++ b/codex-rs/core/src/safety.rs @@ -2,6 +2,8 @@ use std::collections::HashSet; use std::path::Component; use std::path::Path; use std::path::PathBuf; +use std::sync::atomic::AtomicBool; +use std::sync::atomic::Ordering; use codex_apply_patch::ApplyPatchAction; use codex_apply_patch::ApplyPatchFileChange; @@ -13,6 +15,12 @@ use crate::command_safety::is_safe_command::is_known_safe_command; use crate::protocol::AskForApproval; use crate::protocol::SandboxPolicy; +static WINDOWS_SANDBOX_ENABLED: AtomicBool = AtomicBool::new(false); + +pub(crate) fn set_windows_sandbox_enabled(enabled: bool) { + WINDOWS_SANDBOX_ENABLED.store(enabled, Ordering::Relaxed); +} + #[derive(Debug, PartialEq)] pub enum SafetyCheck { AutoApprove { @@ -206,6 +214,12 @@ pub fn get_platform_sandbox() -> Option { Some(SandboxType::MacosSeatbelt) } else if cfg!(target_os = "linux") { Some(SandboxType::LinuxSeccomp) + } else if cfg!(target_os = "windows") { + if WINDOWS_SANDBOX_ENABLED.load(Ordering::Relaxed) { + Some(SandboxType::WindowsAppContainer) + } else { + None + } } else { None } @@ -436,4 +450,19 @@ mod tests { }; assert_eq!(safety_check, expected); } + + #[cfg(target_os = "windows")] + #[test] + fn windows_sandbox_toggle_controls_platform_sandbox() { + set_windows_sandbox_enabled(false); + assert_eq!(get_platform_sandbox(), None); + + set_windows_sandbox_enabled(true); + assert_eq!( + get_platform_sandbox(), + Some(SandboxType::WindowsAppContainer) + ); + + set_windows_sandbox_enabled(false); + } }