adds scaffold for windows sandbox with experimental flag. Does nothing yet.

This commit is contained in:
David Wiesen
2025-10-06 15:25:25 -07:00
parent d73055c5b1
commit 8ec36fc336
3 changed files with 52 additions and 2 deletions

View File

@@ -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<PathBuf>,
/// 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<ReasoningEffort>,
@@ -751,6 +755,7 @@ pub struct ConfigToml {
pub experimental_use_unified_exec_tool: Option<bool>,
pub experimental_use_rmcp_client: Option<bool>,
pub experimental_use_freeform_apply_patch: Option<bool>,
pub experimental_windows_sandbox: Option<bool>,
pub projects: Option<HashMap<String, ProjectConfig>>,
@@ -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),

View File

@@ -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<RawExecToolCallOutput, CodexErr> = 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;
}

View File

@@ -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<SandboxType> {
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);
}
}