mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] Preserve proxy state for filesystem sandbox helpers (#29671)
## 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.
This commit is contained in:
committed by
GitHub
Unverified
parent
ff50b47dce
commit
18fe1d9fe3
@@ -473,6 +473,7 @@ async fn run_command_under_windows_session(
|
||||
) -> ! {
|
||||
use codex_core::windows_sandbox::WindowsSandboxLevelExt;
|
||||
use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
use codex_windows_sandbox::WindowsSandboxProxySettingsMode;
|
||||
use codex_windows_sandbox::WindowsSandboxSessionRequest;
|
||||
use codex_windows_sandbox::spawn_windows_sandbox_session_for_level;
|
||||
|
||||
@@ -485,6 +486,7 @@ async fn run_command_under_windows_session(
|
||||
cwd: cwd.as_path(),
|
||||
env_map: env,
|
||||
windows_sandbox_level: WindowsSandboxLevel::from_config(config),
|
||||
proxy_settings_mode: WindowsSandboxProxySettingsMode::Reconcile,
|
||||
proxy_enforced: false,
|
||||
timeout_ms: None,
|
||||
read_roots_override: None,
|
||||
|
||||
@@ -131,6 +131,8 @@ impl FileSystemSandboxRunner {
|
||||
sandbox_manager
|
||||
.transform_for_direct_spawn(SandboxDirectSpawnTransformRequest {
|
||||
workspace_roots,
|
||||
windows_sandbox_proxy_settings_mode:
|
||||
codex_sandboxing::WindowsSandboxProxySettingsMode::Preserve,
|
||||
transform: SandboxTransformRequest {
|
||||
command,
|
||||
permissions: permission_profile,
|
||||
|
||||
@@ -107,6 +107,8 @@ pub(crate) fn prepare_exec_request(
|
||||
let request = sandbox_manager
|
||||
.transform_for_direct_spawn(SandboxDirectSpawnTransformRequest {
|
||||
workspace_roots,
|
||||
windows_sandbox_proxy_settings_mode:
|
||||
codex_sandboxing::WindowsSandboxProxySettingsMode::Reconcile,
|
||||
transform: SandboxTransformRequest {
|
||||
// TODO(jif): Preserve params.arg0 for the inner command across the sandbox
|
||||
// wrapper, or reject sandboxed requests with a custom arg0.
|
||||
|
||||
@@ -12,6 +12,7 @@ mod windows;
|
||||
pub use bwrap::find_system_bwrap_in_path;
|
||||
#[cfg(target_os = "linux")]
|
||||
pub use bwrap::system_bwrap_warning;
|
||||
pub use codex_windows_sandbox::WindowsSandboxProxySettingsMode;
|
||||
pub use denial::is_likely_sandbox_denied;
|
||||
pub use manager::SandboxCommand;
|
||||
pub use manager::SandboxDirectSpawnTransformRequest;
|
||||
|
||||
@@ -152,6 +152,7 @@ pub struct SandboxTransformRequest<'a> {
|
||||
pub struct SandboxDirectSpawnTransformRequest<'a> {
|
||||
pub transform: SandboxTransformRequest<'a>,
|
||||
pub workspace_roots: &'a [AbsolutePathBuf],
|
||||
pub windows_sandbox_proxy_settings_mode: codex_windows_sandbox::WindowsSandboxProxySettingsMode,
|
||||
}
|
||||
|
||||
// TODO(anp): Revisit this preparation type once this module's PathUri migration is complete.
|
||||
@@ -484,12 +485,14 @@ impl SandboxManager {
|
||||
codex_home: &Path,
|
||||
) -> Result<SandboxExecRequest, SandboxTransformError> {
|
||||
let workspace_roots = request.workspace_roots;
|
||||
let proxy_settings_mode = request.windows_sandbox_proxy_settings_mode;
|
||||
let mut request = self.transform(request.transform)?;
|
||||
if request.sandbox == SandboxType::WindowsRestrictedToken {
|
||||
wrap_windows_sandbox_exec_request_for_direct_spawn(
|
||||
&mut request,
|
||||
workspace_roots,
|
||||
codex_home,
|
||||
proxy_settings_mode,
|
||||
)?;
|
||||
}
|
||||
Ok(request)
|
||||
@@ -501,6 +504,7 @@ fn wrap_windows_sandbox_exec_request_for_direct_spawn(
|
||||
request: &mut SandboxExecRequest,
|
||||
workspace_roots: &[AbsolutePathBuf],
|
||||
codex_home: &Path,
|
||||
proxy_settings_mode: codex_windows_sandbox::WindowsSandboxProxySettingsMode,
|
||||
) -> Result<(), SandboxTransformError> {
|
||||
// TODO(anp): Keep PathUri through the Windows sandbox wrapper boundary.
|
||||
let native_cwd =
|
||||
@@ -572,6 +576,7 @@ fn wrap_windows_sandbox_exec_request_for_direct_spawn(
|
||||
request.windows_sandbox_level,
|
||||
request.windows_sandbox_private_desktop,
|
||||
proxy_enforced,
|
||||
proxy_settings_mode,
|
||||
read_roots_override,
|
||||
read_roots_include_platform_defaults,
|
||||
write_roots_override,
|
||||
|
||||
@@ -499,6 +499,8 @@ fn transform_for_direct_spawn_windows_materializes_inner_helper() {
|
||||
.transform_for_direct_spawn_with_codex_home(
|
||||
SandboxDirectSpawnTransformRequest {
|
||||
workspace_roots: workspace_roots.as_slice(),
|
||||
windows_sandbox_proxy_settings_mode:
|
||||
codex_windows_sandbox::WindowsSandboxProxySettingsMode::Preserve,
|
||||
transform: SandboxTransformRequest {
|
||||
command: SandboxCommand {
|
||||
program: configured_helper.as_os_str().to_owned(),
|
||||
@@ -544,6 +546,12 @@ fn transform_for_direct_spawn_windows_materializes_inner_helper() {
|
||||
.iter()
|
||||
.any(|arg| arg == "--run-as-windows-sandbox")
|
||||
);
|
||||
assert!(
|
||||
exec_request
|
||||
.command
|
||||
.iter()
|
||||
.any(|arg| arg == "--preserve-proxy-settings")
|
||||
);
|
||||
assert!(
|
||||
exec_request
|
||||
.command
|
||||
|
||||
@@ -150,6 +150,7 @@ mod windows_impl {
|
||||
&deny_read_paths_override,
|
||||
&deny_write_paths_override,
|
||||
proxy_enforced,
|
||||
crate::WindowsSandboxProxySettingsMode::Reconcile,
|
||||
)?;
|
||||
// Build capability SID for ACL grants.
|
||||
let caps = load_or_create_cap_sids(codex_home)?;
|
||||
@@ -214,6 +215,7 @@ mod windows_impl {
|
||||
&deny_read_paths_override,
|
||||
&deny_write_paths_override,
|
||||
proxy_enforced,
|
||||
crate::WindowsSandboxProxySettingsMode::Reconcile,
|
||||
)?;
|
||||
spawn_runner_transport(
|
||||
codex_home,
|
||||
|
||||
@@ -8,8 +8,8 @@ use crate::setup::SetupMarker;
|
||||
use crate::setup::gather_read_roots;
|
||||
use crate::setup::gather_write_roots_for_permissions;
|
||||
use crate::setup::offline_proxy_settings_from_env;
|
||||
use crate::setup::run_elevated_setup;
|
||||
use crate::setup::run_setup_refresh_with_overrides;
|
||||
use crate::setup::run_elevated_setup_with_proxy_settings;
|
||||
use crate::setup::run_setup_refresh_with_overrides_and_proxy_settings;
|
||||
use crate::setup::sandbox_users_path;
|
||||
use crate::setup::setup_marker_path;
|
||||
use anyhow::Context;
|
||||
@@ -154,6 +154,7 @@ pub fn require_logon_sandbox_creds(
|
||||
deny_read_paths_override: &[PathBuf],
|
||||
deny_write_paths_override: &[PathBuf],
|
||||
proxy_enforced: bool,
|
||||
proxy_settings_mode: crate::WindowsSandboxProxySettingsMode,
|
||||
) -> Result<SandboxCreds> {
|
||||
let sandbox_dir = crate::setup::sandbox_dir(codex_home);
|
||||
let needed_read = read_roots_override
|
||||
@@ -163,13 +164,19 @@ pub fn require_logon_sandbox_creds(
|
||||
.map(<[PathBuf]>::to_vec)
|
||||
.unwrap_or_else(|| gather_write_roots_for_permissions(permissions, command_cwd, env_map));
|
||||
let network_identity = SandboxNetworkIdentity::from_permissions(permissions, proxy_enforced);
|
||||
let desired_offline_proxy_settings = offline_proxy_settings_from_env(env_map, network_identity);
|
||||
let marker = load_marker(codex_home)?;
|
||||
let desired_offline_proxy_settings = desired_offline_proxy_settings(
|
||||
marker.as_ref(),
|
||||
proxy_settings_mode,
|
||||
env_map,
|
||||
network_identity,
|
||||
);
|
||||
// NOTE: Do not add CODEX_HOME/.sandbox to `needed_write`; it must remain non-writable by the
|
||||
// restricted capability token. The setup helper's `lock_sandbox_dir` is responsible for
|
||||
// granting the sandbox group access to this directory without granting the capability SID.
|
||||
let mut setup_reason: Option<String> = None;
|
||||
|
||||
let mut identity = match load_marker(codex_home)? {
|
||||
let mut identity = match marker {
|
||||
Some(marker) if marker.version_matches() => {
|
||||
if let Some(reason) =
|
||||
marker.request_mismatch_reason(network_identity, &desired_offline_proxy_settings)
|
||||
@@ -201,7 +208,7 @@ pub fn require_logon_sandbox_creds(
|
||||
} else {
|
||||
crate::logging::log_note("sandbox setup required", Some(&sandbox_dir));
|
||||
}
|
||||
run_elevated_setup(
|
||||
run_elevated_setup_with_proxy_settings(
|
||||
crate::setup::SandboxSetupRequest {
|
||||
permissions,
|
||||
command_cwd,
|
||||
@@ -216,11 +223,12 @@ pub fn require_logon_sandbox_creds(
|
||||
deny_read_paths: Some(deny_read_paths_override.to_vec()),
|
||||
deny_write_paths: Some(deny_write_paths_override.to_vec()),
|
||||
},
|
||||
&desired_offline_proxy_settings,
|
||||
)?;
|
||||
identity = select_identity(network_identity, codex_home)?;
|
||||
}
|
||||
// Always refresh ACLs (non-elevated) for current roots via the setup binary.
|
||||
run_setup_refresh_with_overrides(
|
||||
run_setup_refresh_with_overrides_and_proxy_settings(
|
||||
crate::setup::SandboxSetupRequest {
|
||||
permissions,
|
||||
command_cwd,
|
||||
@@ -235,6 +243,7 @@ pub fn require_logon_sandbox_creds(
|
||||
deny_read_paths: Some(deny_read_paths_override.to_vec()),
|
||||
deny_write_paths: Some(deny_write_paths_override.to_vec()),
|
||||
},
|
||||
&desired_offline_proxy_settings,
|
||||
)?;
|
||||
let identity = identity.ok_or_else(|| {
|
||||
anyhow!(
|
||||
@@ -247,6 +256,22 @@ pub fn require_logon_sandbox_creds(
|
||||
})
|
||||
}
|
||||
|
||||
fn desired_offline_proxy_settings(
|
||||
marker: Option<&SetupMarker>,
|
||||
proxy_settings_mode: crate::WindowsSandboxProxySettingsMode,
|
||||
env_map: &HashMap<String, String>,
|
||||
network_identity: SandboxNetworkIdentity,
|
||||
) -> crate::setup::OfflineProxySettings {
|
||||
match (marker, proxy_settings_mode) {
|
||||
(Some(marker), crate::WindowsSandboxProxySettingsMode::Preserve)
|
||||
if marker.version_matches() =>
|
||||
{
|
||||
marker.offline_proxy_settings()
|
||||
}
|
||||
_ => offline_proxy_settings_from_env(env_map, network_identity),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn refresh_logon_sandbox_creds(
|
||||
permissions: &ResolvedWindowsSandboxPermissions,
|
||||
@@ -259,6 +284,7 @@ pub(crate) fn refresh_logon_sandbox_creds(
|
||||
deny_read_paths_override: &[PathBuf],
|
||||
deny_write_paths_override: &[PathBuf],
|
||||
proxy_enforced: bool,
|
||||
proxy_settings_mode: crate::WindowsSandboxProxySettingsMode,
|
||||
) -> Result<SandboxCreds> {
|
||||
remove_sandbox_users_file(codex_home, "sandbox user login failed")?;
|
||||
require_logon_sandbox_creds(
|
||||
@@ -272,13 +298,20 @@ pub(crate) fn refresh_logon_sandbox_creds(
|
||||
deny_read_paths_override,
|
||||
deny_write_paths_override,
|
||||
proxy_enforced,
|
||||
proxy_settings_mode,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::desired_offline_proxy_settings;
|
||||
use super::remove_sandbox_users_file;
|
||||
use crate::WindowsSandboxProxySettingsMode;
|
||||
use crate::setup::SandboxNetworkIdentity;
|
||||
use crate::setup::SetupMarker;
|
||||
use crate::setup::sandbox_users_path;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use tempfile::TempDir;
|
||||
|
||||
@@ -302,4 +335,40 @@ mod tests {
|
||||
remove_sandbox_users_file(codex_home.path(), "stale creds").expect("remove users");
|
||||
assert!(!users_path.exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn preserving_proxy_settings_uses_the_existing_marker() {
|
||||
let marker = SetupMarker {
|
||||
version: crate::setup::SETUP_VERSION,
|
||||
offline_username: "offline".to_string(),
|
||||
online_username: "online".to_string(),
|
||||
created_at: None,
|
||||
proxy_ports: vec![7890],
|
||||
allow_local_binding: true,
|
||||
};
|
||||
let env_map = HashMap::from([(
|
||||
"HTTP_PROXY".to_string(),
|
||||
"http://127.0.0.1:8080".to_string(),
|
||||
)]);
|
||||
|
||||
assert_eq!(
|
||||
desired_offline_proxy_settings(
|
||||
Some(&marker),
|
||||
WindowsSandboxProxySettingsMode::Preserve,
|
||||
&env_map,
|
||||
SandboxNetworkIdentity::Offline,
|
||||
),
|
||||
marker.offline_proxy_settings()
|
||||
);
|
||||
assert_eq!(
|
||||
desired_offline_proxy_settings(
|
||||
Some(&marker),
|
||||
WindowsSandboxProxySettingsMode::Reconcile,
|
||||
&env_map,
|
||||
SandboxNetworkIdentity::Offline,
|
||||
)
|
||||
.proxy_ports,
|
||||
vec![8080]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,15 @@ impl fmt::Debug for WindowsSandboxCancellationToken {
|
||||
}
|
||||
}
|
||||
|
||||
/// Controls whether a Windows sandbox launch reconciles persistent proxy
|
||||
/// firewall settings or preserves the settings established by another launch.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
pub enum WindowsSandboxProxySettingsMode {
|
||||
#[default]
|
||||
Reconcile,
|
||||
Preserve,
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
mod acl;
|
||||
#[cfg(target_os = "windows")]
|
||||
|
||||
@@ -130,14 +130,16 @@ pub fn run_setup_refresh(
|
||||
proxy_enforced,
|
||||
},
|
||||
SetupRootOverrides::default(),
|
||||
/*offline_proxy_settings_override*/ None,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn run_setup_refresh_with_overrides(
|
||||
pub(crate) fn run_setup_refresh_with_overrides_and_proxy_settings(
|
||||
request: SandboxSetupRequest<'_>,
|
||||
overrides: SetupRootOverrides,
|
||||
offline_proxy_settings: &OfflineProxySettings,
|
||||
) -> Result<()> {
|
||||
run_setup_refresh_inner(request, overrides)
|
||||
run_setup_refresh_inner(request, overrides, Some(offline_proxy_settings))
|
||||
}
|
||||
|
||||
pub fn run_setup_refresh_with_extra_read_roots(
|
||||
@@ -174,12 +176,14 @@ pub fn run_setup_refresh_with_extra_read_roots(
|
||||
deny_read_paths: None,
|
||||
deny_write_paths: None,
|
||||
},
|
||||
/*offline_proxy_settings_override*/ None,
|
||||
)
|
||||
}
|
||||
|
||||
fn run_setup_refresh_inner(
|
||||
request: SandboxSetupRequest<'_>,
|
||||
overrides: SetupRootOverrides,
|
||||
offline_proxy_settings_override: Option<&OfflineProxySettings>,
|
||||
) -> Result<()> {
|
||||
if !request.permissions.is_enforceable_by_windows_sandbox() {
|
||||
anyhow::bail!("unsupported filesystem permissions for Windows sandbox setup");
|
||||
@@ -187,9 +191,8 @@ fn run_setup_refresh_inner(
|
||||
let (read_roots, write_roots) = build_payload_roots(&request, &overrides);
|
||||
let deny_read_paths = build_payload_deny_read_paths(overrides.deny_read_paths);
|
||||
let deny_write_paths = build_payload_deny_write_paths(&request, overrides.deny_write_paths);
|
||||
let network_identity =
|
||||
SandboxNetworkIdentity::from_permissions(request.permissions, request.proxy_enforced);
|
||||
let offline_proxy_settings = offline_proxy_settings_from_env(request.env_map, network_identity);
|
||||
let offline_proxy_settings =
|
||||
offline_proxy_settings_for_request(&request, offline_proxy_settings_override);
|
||||
let payload = ElevationPayload {
|
||||
version: SETUP_VERSION,
|
||||
offline_username: OFFLINE_USERNAME.to_string(),
|
||||
@@ -283,6 +286,13 @@ impl SetupMarker {
|
||||
self.version == SETUP_VERSION
|
||||
}
|
||||
|
||||
pub(crate) fn offline_proxy_settings(&self) -> OfflineProxySettings {
|
||||
OfflineProxySettings {
|
||||
proxy_ports: self.proxy_ports.clone(),
|
||||
allow_local_binding: self.allow_local_binding,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn request_mismatch_reason(
|
||||
&self,
|
||||
network_identity: SandboxNetworkIdentity,
|
||||
@@ -593,6 +603,17 @@ pub(crate) fn offline_proxy_settings_from_env(
|
||||
}
|
||||
}
|
||||
|
||||
fn offline_proxy_settings_for_request(
|
||||
request: &SandboxSetupRequest<'_>,
|
||||
offline_proxy_settings_override: Option<&OfflineProxySettings>,
|
||||
) -> OfflineProxySettings {
|
||||
offline_proxy_settings_override.cloned().unwrap_or_else(|| {
|
||||
let network_identity =
|
||||
SandboxNetworkIdentity::from_permissions(request.permissions, request.proxy_enforced);
|
||||
offline_proxy_settings_from_env(request.env_map, network_identity)
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn proxy_ports_from_env(env_map: &HashMap<String, String>) -> Vec<u16> {
|
||||
let mut ports = BTreeSet::new();
|
||||
for key in PROXY_ENV_KEYS {
|
||||
@@ -821,6 +842,24 @@ fn run_setup_exe(
|
||||
pub fn run_elevated_setup(
|
||||
request: SandboxSetupRequest<'_>,
|
||||
overrides: SetupRootOverrides,
|
||||
) -> Result<()> {
|
||||
run_elevated_setup_inner(
|
||||
request, overrides, /*offline_proxy_settings_override*/ None,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn run_elevated_setup_with_proxy_settings(
|
||||
request: SandboxSetupRequest<'_>,
|
||||
overrides: SetupRootOverrides,
|
||||
offline_proxy_settings: &OfflineProxySettings,
|
||||
) -> Result<()> {
|
||||
run_elevated_setup_inner(request, overrides, Some(offline_proxy_settings))
|
||||
}
|
||||
|
||||
fn run_elevated_setup_inner(
|
||||
request: SandboxSetupRequest<'_>,
|
||||
overrides: SetupRootOverrides,
|
||||
offline_proxy_settings_override: Option<&OfflineProxySettings>,
|
||||
) -> Result<()> {
|
||||
if !request.permissions.is_enforceable_by_windows_sandbox() {
|
||||
anyhow::bail!("unsupported filesystem permissions for Windows sandbox setup");
|
||||
@@ -836,9 +875,8 @@ pub fn run_elevated_setup(
|
||||
let (read_roots, write_roots) = build_payload_roots(&request, &overrides);
|
||||
let deny_read_paths = build_payload_deny_read_paths(overrides.deny_read_paths);
|
||||
let deny_write_paths = build_payload_deny_write_paths(&request, overrides.deny_write_paths);
|
||||
let network_identity =
|
||||
SandboxNetworkIdentity::from_permissions(request.permissions, request.proxy_enforced);
|
||||
let offline_proxy_settings = offline_proxy_settings_from_env(request.env_map, network_identity);
|
||||
let offline_proxy_settings =
|
||||
offline_proxy_settings_for_request(&request, offline_proxy_settings_override);
|
||||
let payload = ElevationPayload {
|
||||
version: SETUP_VERSION,
|
||||
offline_username: OFFLINE_USERNAME.to_string(),
|
||||
@@ -1170,6 +1208,37 @@ mod tests {
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn setup_request_prefers_explicit_proxy_settings() {
|
||||
let tmp = TempDir::new().expect("tempdir");
|
||||
let command_cwd = tmp.path().join("workspace");
|
||||
fs::create_dir_all(&command_cwd).expect("create workspace");
|
||||
let permissions = permissions_for(
|
||||
&PermissionProfile::read_only(),
|
||||
workspace_roots_for(&command_cwd).as_slice(),
|
||||
);
|
||||
let env_map = HashMap::from([(
|
||||
"HTTP_PROXY".to_string(),
|
||||
"http://127.0.0.1:8080".to_string(),
|
||||
)]);
|
||||
let explicit = super::OfflineProxySettings {
|
||||
proxy_ports: vec![7890],
|
||||
allow_local_binding: true,
|
||||
};
|
||||
let request = super::SandboxSetupRequest {
|
||||
permissions: &permissions,
|
||||
command_cwd: &command_cwd,
|
||||
env_map: &env_map,
|
||||
codex_home: tmp.path(),
|
||||
proxy_enforced: false,
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
super::offline_proxy_settings_for_request(&request, Some(&explicit)),
|
||||
explicit
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn report_helper_failure_uses_setup_error_report_when_clear_succeeded() {
|
||||
let tmp = TempDir::new().expect("tempdir");
|
||||
|
||||
@@ -357,6 +357,7 @@ pub(crate) fn prepare_elevated_spawn_context_for_permissions(
|
||||
deny_read_paths_override: &[PathBuf],
|
||||
deny_write_paths_override: &[PathBuf],
|
||||
proxy_enforced: bool,
|
||||
proxy_settings_mode: crate::WindowsSandboxProxySettingsMode,
|
||||
) -> Result<ElevatedSpawnContext> {
|
||||
normalize_null_device_env(env_map);
|
||||
ensure_non_interactive_pager(env_map);
|
||||
@@ -412,6 +413,7 @@ pub(crate) fn prepare_elevated_spawn_context_for_permissions(
|
||||
deny_write_paths_override
|
||||
},
|
||||
proxy_enforced,
|
||||
proxy_settings_mode,
|
||||
)?;
|
||||
let caps = load_or_create_cap_sids(codex_home)?;
|
||||
let (psid_to_use, cap_sids) = if uses_write_capabilities {
|
||||
|
||||
@@ -56,6 +56,7 @@ pub(crate) async fn spawn_windows_sandbox_session_elevated_for_permission_profil
|
||||
cwd: &Path,
|
||||
mut env_map: HashMap<String, String>,
|
||||
proxy_enforced: bool,
|
||||
proxy_settings_mode: crate::WindowsSandboxProxySettingsMode,
|
||||
timeout_ms: Option<u64>,
|
||||
read_roots_override: Option<&[PathBuf]>,
|
||||
read_roots_include_platform_defaults: bool,
|
||||
@@ -91,6 +92,7 @@ pub(crate) async fn spawn_windows_sandbox_session_elevated_for_permission_profil
|
||||
&deny_read_paths_override,
|
||||
&deny_write_paths_override,
|
||||
proxy_enforced,
|
||||
proxy_settings_mode,
|
||||
)?;
|
||||
|
||||
let spawn_request = SpawnRequest {
|
||||
@@ -133,6 +135,7 @@ pub(crate) async fn spawn_windows_sandbox_session_elevated_for_permission_profil
|
||||
&deny_read_paths_override,
|
||||
&deny_write_paths_override,
|
||||
/*proxy_enforced*/ false,
|
||||
proxy_settings_mode,
|
||||
)?;
|
||||
spawn_runner_transport_task(
|
||||
codex_home,
|
||||
|
||||
@@ -31,6 +31,7 @@ pub struct WindowsSandboxSessionRequest<'a> {
|
||||
pub env_map: HashMap<String, String>,
|
||||
pub windows_sandbox_level: WindowsSandboxLevel,
|
||||
pub proxy_enforced: bool,
|
||||
pub proxy_settings_mode: crate::WindowsSandboxProxySettingsMode,
|
||||
pub timeout_ms: Option<u64>,
|
||||
pub read_roots_override: Option<&'a [PathBuf]>,
|
||||
pub read_roots_include_platform_defaults: bool,
|
||||
@@ -48,7 +49,7 @@ pub async fn spawn_windows_sandbox_session_for_level(
|
||||
if request.proxy_enforced
|
||||
|| matches!(request.windows_sandbox_level, WindowsSandboxLevel::Elevated)
|
||||
{
|
||||
spawn_windows_sandbox_session_elevated_for_permission_profile(
|
||||
backends::elevated::spawn_windows_sandbox_session_elevated_for_permission_profile(
|
||||
request.permission_profile,
|
||||
request.workspace_roots,
|
||||
request.codex_home,
|
||||
@@ -56,6 +57,7 @@ pub async fn spawn_windows_sandbox_session_for_level(
|
||||
request.cwd,
|
||||
request.env_map,
|
||||
request.proxy_enforced,
|
||||
request.proxy_settings_mode,
|
||||
request.timeout_ms,
|
||||
request.read_roots_override,
|
||||
request.read_roots_include_platform_defaults,
|
||||
@@ -145,6 +147,7 @@ pub async fn spawn_windows_sandbox_session_elevated_for_permission_profile(
|
||||
cwd,
|
||||
env_map,
|
||||
proxy_enforced,
|
||||
crate::WindowsSandboxProxySettingsMode::Reconcile,
|
||||
timeout_ms,
|
||||
read_roots_override,
|
||||
read_roots_include_platform_defaults,
|
||||
|
||||
@@ -26,6 +26,7 @@ const DENY_WRITE_PATHS_JSON_FLAG: &str = "--deny-write-paths-json";
|
||||
const ENV_JSON_FLAG: &str = "--env-json";
|
||||
const PERMISSION_PROFILE_FLAG: &str = "--permission-profile";
|
||||
const PRIVATE_DESKTOP_FLAG: &str = "--windows-sandbox-private-desktop";
|
||||
const PRESERVE_PROXY_SETTINGS_FLAG: &str = "--preserve-proxy-settings";
|
||||
const PROXY_ENFORCED_FLAG: &str = "--proxy-enforced";
|
||||
const READ_ROOTS_INCLUDE_PLATFORM_DEFAULTS_FLAG: &str = "--read-roots-include-platform-defaults";
|
||||
const READ_ROOTS_JSON_FLAG: &str = "--read-roots-json";
|
||||
@@ -43,6 +44,7 @@ pub fn create_windows_sandbox_command_args_for_permission_profile(
|
||||
windows_sandbox_level: WindowsSandboxLevel,
|
||||
windows_sandbox_private_desktop: bool,
|
||||
proxy_enforced: bool,
|
||||
proxy_settings_mode: crate::WindowsSandboxProxySettingsMode,
|
||||
read_roots_override: Option<&[PathBuf]>,
|
||||
read_roots_include_platform_defaults: bool,
|
||||
write_roots_override: Option<&[PathBuf]>,
|
||||
@@ -82,6 +84,9 @@ pub fn create_windows_sandbox_command_args_for_permission_profile(
|
||||
if proxy_enforced {
|
||||
args.push(PROXY_ENFORCED_FLAG.to_string());
|
||||
}
|
||||
if proxy_settings_mode == crate::WindowsSandboxProxySettingsMode::Preserve {
|
||||
args.push(PRESERVE_PROXY_SETTINGS_FLAG.to_string());
|
||||
}
|
||||
if let Some(read_roots_override) = read_roots_override {
|
||||
push_json_arg(&mut args, READ_ROOTS_JSON_FLAG, &read_roots_override);
|
||||
}
|
||||
@@ -154,6 +159,7 @@ struct WindowsSandboxWrapperRequest {
|
||||
windows_sandbox_level: WindowsSandboxLevel,
|
||||
windows_sandbox_private_desktop: bool,
|
||||
proxy_enforced: bool,
|
||||
proxy_settings_mode: crate::WindowsSandboxProxySettingsMode,
|
||||
read_roots_override: Option<Vec<PathBuf>>,
|
||||
read_roots_include_platform_defaults: bool,
|
||||
write_roots_override: Option<Vec<PathBuf>>,
|
||||
@@ -176,6 +182,7 @@ async fn run_windows_sandbox_wrapper_request(request: WindowsSandboxWrapperReque
|
||||
env_map: request.env_map,
|
||||
windows_sandbox_level: request.windows_sandbox_level,
|
||||
proxy_enforced: request.proxy_enforced,
|
||||
proxy_settings_mode: request.proxy_settings_mode,
|
||||
timeout_ms: None,
|
||||
read_roots_override: request.read_roots_override.as_deref(),
|
||||
read_roots_include_platform_defaults: request.read_roots_include_platform_defaults,
|
||||
@@ -201,6 +208,7 @@ fn parse_windows_sandbox_wrapper_args(args: Vec<String>) -> Result<WindowsSandbo
|
||||
let mut windows_sandbox_level = None;
|
||||
let mut windows_sandbox_private_desktop = false;
|
||||
let mut proxy_enforced = false;
|
||||
let mut proxy_settings_mode = crate::WindowsSandboxProxySettingsMode::Reconcile;
|
||||
let mut read_roots_override = None;
|
||||
let mut read_roots_include_platform_defaults = false;
|
||||
let mut write_roots_override = None;
|
||||
@@ -240,6 +248,9 @@ fn parse_windows_sandbox_wrapper_args(args: Vec<String>) -> Result<WindowsSandbo
|
||||
windows_sandbox_level = Some(parse_windows_sandbox_level(&value)?);
|
||||
}
|
||||
PRIVATE_DESKTOP_FLAG => windows_sandbox_private_desktop = true,
|
||||
PRESERVE_PROXY_SETTINGS_FLAG => {
|
||||
proxy_settings_mode = crate::WindowsSandboxProxySettingsMode::Preserve;
|
||||
}
|
||||
PROXY_ENFORCED_FLAG => proxy_enforced = true,
|
||||
READ_ROOTS_INCLUDE_PLATFORM_DEFAULTS_FLAG => {
|
||||
read_roots_include_platform_defaults = true;
|
||||
@@ -282,6 +293,7 @@ fn parse_windows_sandbox_wrapper_args(args: Vec<String>) -> Result<WindowsSandbo
|
||||
.ok_or_else(|| anyhow!("missing required {SANDBOX_LEVEL_FLAG}"))?,
|
||||
windows_sandbox_private_desktop,
|
||||
proxy_enforced,
|
||||
proxy_settings_mode,
|
||||
read_roots_override,
|
||||
read_roots_include_platform_defaults,
|
||||
write_roots_override,
|
||||
|
||||
@@ -15,6 +15,7 @@ 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;
|
||||
@@ -61,6 +62,7 @@ fn windows_wrapper_args_round_trip() {
|
||||
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()),
|
||||
@@ -78,6 +80,7 @@ fn windows_wrapper_args_round_trip() {
|
||||
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()));
|
||||
@@ -98,6 +101,10 @@ fn windows_wrapper_args_round_trip() {
|
||||
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));
|
||||
|
||||
Reference in New Issue
Block a user