Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 77 additions & 12 deletions codex-rs/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions codex-rs/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,27 @@ seccompiler = { workspace = true }
[target.'cfg(target_os = "macos")'.dependencies]
core-foundation = "0.9"

[target.'cfg(windows)'.dependencies]
windows = { version = "0.58", features = [
"Win32_Foundation",
"Win32_Security_Isolation",
"Win32_Security",
"Win32_Security_Authorization",
"Win32_Storage_FileSystem",
"Win32_System_Memory",
"Win32_System_Threading",
] }

[features]
default = []
windows_appcontainer_command_ext = []
windows_appcontainer_command_ext_raw_attribute = [
"windows_appcontainer_command_ext",
]
windows_appcontainer_raw_attribute_api = [
"windows_appcontainer_command_ext_raw_attribute",
]

# Build OpenSSL from source for musl builds.
[target.x86_64-unknown-linux-musl.dependencies]
openssl-sys = { workspace = true, features = ["vendored"] }
Expand Down
13 changes: 13 additions & 0 deletions codex-rs/core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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>,
Expand Down Expand Up @@ -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>>,

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1146,6 +1154,7 @@ impl Config {
}
},
};
set_windows_sandbox_enabled(config.experimental_windows_sandbox);
Ok(config)
}

Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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),
Expand Down
35 changes: 34 additions & 1 deletion codex-rs/core/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ use crate::protocol::SandboxPolicy;
use crate::seatbelt::spawn_command_under_seatbelt;
use crate::spawn::StdioPolicy;
use crate::spawn::spawn_child_async;
#[cfg(windows)]
use crate::windows_appcontainer::spawn_command_under_windows_appcontainer;

const DEFAULT_TIMEOUT_MS: u64 = 10_000;

Expand Down Expand Up @@ -70,6 +72,9 @@ pub enum SandboxType {

/// Only available on Linux.
LinuxSeccomp,

/// Only available on Windows.
WindowsAppContainer,
}

#[derive(Clone)]
Expand All @@ -94,6 +99,31 @@ 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::WindowsAppContainer => {
#[cfg(windows)]
{
let ExecParams {
command,
cwd: command_cwd,
env,
..
} = params;
let child = spawn_command_under_windows_appcontainer(
command,
command_cwd,
sandbox_policy,
sandbox_cwd,
StdioPolicy::RedirectForShellTool,
env,
)
.await?;
consume_truncated_output(child, timeout_duration, stdout_stream.clone()).await
}
#[cfg(not(windows))]
{
panic!("windows sandboxing is not available on this platform");
}
}
SandboxType::MacosSeatbelt => {
let ExecParams {
command,
Expand Down Expand Up @@ -198,7 +228,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;
}

Expand Down
7 changes: 7 additions & 0 deletions codex-rs/core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
//! Root of the `codex-core` library.

#![cfg_attr(
all(windows, feature = "windows_appcontainer_raw_attribute_api"),
feature(windows_process_extensions_raw_attribute)
)]
// Prevent accidental direct writes to stdout/stderr in library code. All
// user-visible output must go through the appropriate abstraction (e.g.,
// the TUI or the tracing stack).
Expand Down Expand Up @@ -82,6 +86,9 @@ mod tasks;
mod user_notification;
pub mod util;

#[cfg(windows)]
pub mod windows_appcontainer;

pub use apply_patch::CODEX_APPLY_PATCH_ARG1;
pub use command_safety::is_safe_command;
pub use safety::get_platform_sandbox;
Expand Down
Loading
Loading