mirror of
https://github.com/openai/codex.git
synced 2026-11-13 06:45:07 +00:00
## Why Filesystem helpers intentionally run with a minimal environment that excludes proxy variables. After filesystem operations started using the Windows sandbox wrapper, the wrapper derived an empty proxy configuration from that helper environment and compared it with the persistent sandbox setup marker. When the marker contained proxy ports, every filesystem operation appeared to require a firewall update, which could launch elevated setup, show a UAC or loader dialog, and fail operations such as `apply_patch` with error 1223. Filesystem helpers do not use network access, so they should preserve the proxy/firewall state established by normal sandboxed process launches. ## What changed - Add an explicit Windows sandbox proxy-settings mode for reconciling or preserving persistent proxy state. - Use preserve mode for filesystem helpers while normal process launches continue to reconcile proxy settings from their environment. - Carry the selected proxy state consistently through setup validation, elevated setup, and non-elevated ACL refreshes. - Cover wrapper argument propagation and marker-derived proxy preservation. ## Validation - `cargo build -p codex-cli --bin codex` - `just test -p codex-windows-sandbox preserving_proxy_settings_uses_the_existing_marker` - `just test -p codex-windows-sandbox windows_wrapper_args_round_trip` - `just test -p codex-windows-sandbox setup_request_prefers_explicit_proxy_settings` - `just test -p codex-sandboxing transform_for_direct_spawn_windows` - `just test -p codex-exec-server fs_sandbox::tests` - Ran the same sandboxed `fs/writeFile` reproduction against published `0.142.0-alpha.6` and the new CLI. The published CLI launched elevated setup and failed with `ShellExecuteExW ... 1223`; the new CLI completed without elevation. Related to #28359.
114 lines
4.7 KiB
Rust
114 lines
4.7 KiB
Rust
use std::collections::HashMap;
|
|
use std::path::Path;
|
|
use std::path::PathBuf;
|
|
|
|
use codex_protocol::config_types::WindowsSandboxLevel;
|
|
use codex_protocol::models::PermissionProfile;
|
|
use codex_protocol::permissions::NetworkSandboxPolicy;
|
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
use super::CODEX_HOME_FLAG;
|
|
use super::CODEX_WINDOWS_SANDBOX_ARG1;
|
|
use super::COMMAND_CWD_FLAG;
|
|
use super::DENY_READ_PATHS_JSON_FLAG;
|
|
use super::DENY_WRITE_PATHS_JSON_FLAG;
|
|
use super::ENV_JSON_FLAG;
|
|
use super::PERMISSION_PROFILE_FLAG;
|
|
use super::PRESERVE_PROXY_SETTINGS_FLAG;
|
|
use super::PRIVATE_DESKTOP_FLAG;
|
|
use super::PROXY_ENFORCED_FLAG;
|
|
use super::READ_ROOTS_INCLUDE_PLATFORM_DEFAULTS_FLAG;
|
|
use super::READ_ROOTS_JSON_FLAG;
|
|
use super::SANDBOX_LEVEL_FLAG;
|
|
use super::WORKSPACE_ROOT_FLAG;
|
|
use super::WRITE_ROOTS_JSON_FLAG;
|
|
use super::create_windows_sandbox_command_args_for_permission_profile;
|
|
use super::parse_windows_sandbox_wrapper_args;
|
|
|
|
#[test]
|
|
fn windows_wrapper_args_round_trip() {
|
|
let command_cwd = AbsolutePathBuf::from_absolute_path(Path::new(r"C:\workspace"))
|
|
.expect("absolute command cwd");
|
|
let workspace_roots = vec![
|
|
command_cwd.clone(),
|
|
AbsolutePathBuf::from_absolute_path(Path::new(r"D:\other-workspace"))
|
|
.expect("absolute workspace root"),
|
|
];
|
|
let env = HashMap::from([("Path".to_string(), r"C:\Windows\System32".to_string())]);
|
|
let permission_profile = PermissionProfile::External {
|
|
network: NetworkSandboxPolicy::Restricted,
|
|
};
|
|
let read_roots_override = vec![PathBuf::from(r"C:\read")];
|
|
let write_roots_override = vec![PathBuf::from(r"C:\write")];
|
|
let deny_read_paths_override = vec![
|
|
AbsolutePathBuf::from_absolute_path(Path::new(r"C:\blocked-read"))
|
|
.expect("absolute deny-read"),
|
|
];
|
|
let deny_write_paths_override = vec![
|
|
AbsolutePathBuf::from_absolute_path(Path::new(r"C:\blocked-write"))
|
|
.expect("absolute deny-write"),
|
|
];
|
|
|
|
let args = create_windows_sandbox_command_args_for_permission_profile(
|
|
vec![
|
|
"codex.exe".to_string(),
|
|
"--codex-run-as-fs-helper".to_string(),
|
|
],
|
|
&command_cwd,
|
|
workspace_roots.as_slice(),
|
|
&env,
|
|
&permission_profile,
|
|
WindowsSandboxLevel::Elevated,
|
|
/*windows_sandbox_private_desktop*/ true,
|
|
/*proxy_enforced*/ true,
|
|
crate::WindowsSandboxProxySettingsMode::Preserve,
|
|
Some(read_roots_override.as_slice()),
|
|
/*read_roots_include_platform_defaults*/ true,
|
|
Some(write_roots_override.as_slice()),
|
|
deny_read_paths_override.as_slice(),
|
|
deny_write_paths_override.as_slice(),
|
|
Path::new(r"C:\Users\me\.codex"),
|
|
);
|
|
|
|
assert_eq!(args[0], CODEX_WINDOWS_SANDBOX_ARG1);
|
|
assert!(args.contains(&CODEX_HOME_FLAG.to_string()));
|
|
assert!(args.contains(&COMMAND_CWD_FLAG.to_string()));
|
|
assert!(args.contains(&WORKSPACE_ROOT_FLAG.to_string()));
|
|
assert!(args.contains(&PERMISSION_PROFILE_FLAG.to_string()));
|
|
assert!(args.contains(&ENV_JSON_FLAG.to_string()));
|
|
assert!(args.contains(&SANDBOX_LEVEL_FLAG.to_string()));
|
|
assert!(args.contains(&PRIVATE_DESKTOP_FLAG.to_string()));
|
|
assert!(args.contains(&PROXY_ENFORCED_FLAG.to_string()));
|
|
assert!(args.contains(&PRESERVE_PROXY_SETTINGS_FLAG.to_string()));
|
|
assert!(args.contains(&READ_ROOTS_JSON_FLAG.to_string()));
|
|
assert!(args.contains(&READ_ROOTS_INCLUDE_PLATFORM_DEFAULTS_FLAG.to_string()));
|
|
assert!(args.contains(&WRITE_ROOTS_JSON_FLAG.to_string()));
|
|
assert!(args.contains(&DENY_READ_PATHS_JSON_FLAG.to_string()));
|
|
assert!(args.contains(&DENY_WRITE_PATHS_JSON_FLAG.to_string()));
|
|
|
|
let parsed =
|
|
parse_windows_sandbox_wrapper_args(args[1..].to_vec()).expect("parse wrapper args");
|
|
|
|
assert_eq!(
|
|
parsed.command,
|
|
vec!["codex.exe", "--codex-run-as-fs-helper"]
|
|
);
|
|
assert_eq!(parsed.command_cwd, command_cwd);
|
|
assert_eq!(parsed.workspace_roots, workspace_roots);
|
|
assert_eq!(parsed.env_map, env);
|
|
assert_eq!(parsed.permission_profile, permission_profile);
|
|
assert_eq!(parsed.windows_sandbox_level, WindowsSandboxLevel::Elevated);
|
|
assert_eq!(parsed.windows_sandbox_private_desktop, true);
|
|
assert_eq!(parsed.proxy_enforced, true);
|
|
assert_eq!(
|
|
parsed.proxy_settings_mode,
|
|
crate::WindowsSandboxProxySettingsMode::Preserve
|
|
);
|
|
assert_eq!(parsed.read_roots_override, Some(read_roots_override));
|
|
assert_eq!(parsed.read_roots_include_platform_defaults, true);
|
|
assert_eq!(parsed.write_roots_override, Some(write_roots_override));
|
|
assert_eq!(parsed.deny_read_paths_override, deny_read_paths_override);
|
|
assert_eq!(parsed.deny_write_paths_override, deny_write_paths_override);
|
|
}
|