Skip to content
Closed
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
25 changes: 0 additions & 25 deletions codex-rs/core/src/tools/spec_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,31 +295,6 @@ fn build_specs_with_unavailable_tools(
)
}

#[tokio::test]
async fn model_provided_unified_exec_is_blocked_for_windows_sandboxed_policies() {
let mut model_info = model_info_from_models_json("gpt-5.4").await;
model_info.shell_type = ConfigShellToolType::UnifiedExec;
let features = Features::with_defaults();
let available_models = Vec::new();
let config = ToolsConfig::new(&ToolsConfigParams {
model_info: &model_info,
available_models: &available_models,
features: &features,
image_generation_tool_auth_allowed: true,
web_search_mode: Some(WebSearchMode::Cached),
session_source: SessionSource::Cli,
sandbox_policy: &SandboxPolicy::new_workspace_write_policy(),
windows_sandbox_level: WindowsSandboxLevel::RestrictedToken,
});

let expected_shell_type = if cfg!(target_os = "windows") {
ConfigShellToolType::ShellCommand
} else {
ConfigShellToolType::UnifiedExec
};
assert_eq!(config.shell_type, expected_shell_type);
}

#[tokio::test]
async fn get_memory_requires_feature_flag() {
let config = test_config().await;
Expand Down
35 changes: 10 additions & 25 deletions codex-rs/tools/src/tool_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,7 @@ impl ToolsConfig {
image_generation_tool_auth_allowed,
web_search_mode,
session_source,
sandbox_policy,
windows_sandbox_level,
..
} = params;
let include_apply_patch_tool = features.enabled(Feature::ApplyPatchFreeform);
let include_code_mode = features.enabled(Feature::CodeMode);
Expand Down Expand Up @@ -167,26 +166,25 @@ impl ToolsConfig {
} else {
ShellCommandBackendConfig::Classic
};
let unified_exec_allowed = unified_exec_allowed_in_environment(
cfg!(target_os = "windows"),
sandbox_policy,
*windows_sandbox_level,
);
let unified_exec_enabled = features.enabled(Feature::UnifiedExec);
let model_shell_type = match model_info.shell_type {
ConfigShellToolType::UnifiedExec if !unified_exec_enabled => {
ConfigShellToolType::ShellCommand
}
other => other,
};
let shell_type = if !features.enabled(Feature::ShellTool) {
ConfigShellToolType::Disabled
} else if features.enabled(Feature::ShellZshFork) {
ConfigShellToolType::ShellCommand
} else if features.enabled(Feature::UnifiedExec) && unified_exec_allowed {
} else if unified_exec_enabled {
if codex_utils_pty::conpty_supported() {
ConfigShellToolType::UnifiedExec
} else {
ConfigShellToolType::ShellCommand
}
} else if model_info.shell_type == ConfigShellToolType::UnifiedExec && !unified_exec_allowed
{
ConfigShellToolType::ShellCommand
} else {
model_info.shell_type
model_shell_type
};

let apply_patch_tool_type = match model_info.apply_patch_tool_type {
Expand Down Expand Up @@ -309,19 +307,6 @@ fn supports_image_generation(model_info: &ModelInfo) -> bool {
model_info.input_modalities.contains(&InputModality::Image)
}

fn unified_exec_allowed_in_environment(
is_windows: bool,
sandbox_policy: &SandboxPolicy,
windows_sandbox_level: WindowsSandboxLevel,
) -> bool {
!(is_windows
&& windows_sandbox_level != WindowsSandboxLevel::Disabled
&& !matches!(
sandbox_policy,
SandboxPolicy::DangerFullAccess | SandboxPolicy::ExternalSandbox { .. }
))
}

#[cfg(test)]
#[path = "tool_config_tests.rs"]
mod tests;
39 changes: 18 additions & 21 deletions codex-rs/tools/src/tool_config_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,27 +50,24 @@ fn model_info() -> ModelInfo {
}

#[test]
fn unified_exec_is_blocked_for_windows_sandboxed_policies_only() {
assert!(!unified_exec_allowed_in_environment(
/*is_windows*/ true,
&SandboxPolicy::new_read_only_policy(),
WindowsSandboxLevel::RestrictedToken,
));
assert!(!unified_exec_allowed_in_environment(
/*is_windows*/ true,
&SandboxPolicy::new_workspace_write_policy(),
WindowsSandboxLevel::RestrictedToken,
));
assert!(unified_exec_allowed_in_environment(
/*is_windows*/ true,
&SandboxPolicy::DangerFullAccess,
WindowsSandboxLevel::RestrictedToken,
));
assert!(unified_exec_allowed_in_environment(
/*is_windows*/ true,
&SandboxPolicy::DangerFullAccess,
WindowsSandboxLevel::Disabled,
));
fn model_provided_unified_exec_requires_feature_flag() {
let model_info = model_info();
let mut features = Features::with_defaults();
features.disable(Feature::UnifiedExec);

let available_models = Vec::new();
let tools_config = ToolsConfig::new(&ToolsConfigParams {
model_info: &model_info,
available_models: &available_models,
features: &features,
image_generation_tool_auth_allowed: true,
web_search_mode: Some(WebSearchMode::Cached),
session_source: SessionSource::Cli,
sandbox_policy: &SandboxPolicy::DangerFullAccess,
windows_sandbox_level: WindowsSandboxLevel::Disabled,
});

assert_eq!(tools_config.shell_type, ConfigShellToolType::ShellCommand);
}

#[test]
Expand Down
6 changes: 3 additions & 3 deletions codex-rs/windows-sandbox-rs/src/proc_thread_attr.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::io;
use std::ffi::c_void;
use windows_sys::Win32::Foundation::GetLastError;
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::System::Threading::DeleteProcThreadAttributeList;
Expand Down Expand Up @@ -45,14 +46,13 @@ impl ProcThreadAttributeList {

pub fn set_pseudoconsole(&mut self, hpc: isize) -> io::Result<()> {
let list = self.as_mut_ptr();
let mut hpc_value = hpc;
let ok = unsafe {
UpdateProcThreadAttribute(
list,
0,
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
(&mut hpc_value as *mut isize).cast(),
std::mem::size_of::<isize>(),
hpc as *mut c_void,
std::mem::size_of::<HANDLE>(),
std::ptr::null_mut(),
std::ptr::null_mut(),
)
Expand Down
Loading