Wire Windows sandbox selection into managed proxy routing (#45757)

## What changed

- Track the Windows sandbox implementation separately from its legacy setup level.
- Select dedicated proxy listeners for `WindowsMxc` on Windows across sessions, app-server command execution, and the sandbox CLI.
- Rebuild the session proxy when routing changes, retaining its network policy decider.
- Add a sandbox CLI execution path through the MXC sandbox transform when `WindowsMxc` is selected.

## Testing

Extend configuration assertions for the selected sandbox type and the session refresh test to verify dedicated routing and policy decider retention on Windows.

GitOrigin-RevId: 2a22192636c542022ec81a378a16c1bb6867e145
This commit is contained in:
iceweasel-oai
2026-09-15 18:41:13 +00:00
committed by copyberry
parent af1fc2dbff
commit a5c15ab5c0
14 changed files with 185 additions and 18 deletions
+1
View File
@@ -2635,6 +2635,7 @@ dependencies = [
"codex-utils-cargo-bin",
"codex-utils-cli",
"codex-utils-path",
"codex-utils-path-uri",
"codex-utils-pty",
"codex-windows-sandbox",
"crossterm",
@@ -1,5 +1,6 @@
use super::*;
use codex_core::exec_env::inject_apply_patch_env;
use codex_core::windows_sandbox::managed_proxy_routing_for_windows_sandbox;
use codex_protocol::shell_environment::is_non_inheritable_env_var;
#[derive(Clone)]
@@ -262,6 +263,9 @@ impl CommandExecRequestProcessor {
Some(spec) => match spec
.start_proxy(
&network_proxy_permission_profile,
managed_proxy_routing_for_windows_sandbox(
self.config.permissions.windows_sandbox_type,
),
/*policy_decider*/ None,
/*blocked_request_observer*/ None,
managed_network_requirements_enabled,
+1
View File
@@ -73,6 +73,7 @@ codex-thread-store = { workspace = true }
codex-tui = { workspace = true }
codex-utils-absolute-path = { workspace = true }
codex-utils-path = { workspace = true }
codex-utils-path-uri = { workspace = true }
crossterm = { workspace = true, features = ["event-stream"] }
futures = { workspace = true }
http = { workspace = true }
+64 -11
View File
@@ -19,6 +19,7 @@ use codex_core::exec_env::create_env;
#[cfg(target_os = "macos")]
use codex_core::spawn::CODEX_SANDBOX_ENV_VAR;
use codex_core::spawn::CODEX_SANDBOX_NETWORK_DISABLED_ENV_VAR;
use codex_core::windows_sandbox::managed_proxy_routing_for_windows_sandbox;
use codex_protocol::config_types::SandboxMode;
use codex_protocol::models::PermissionProfile;
use codex_protocol::models::SandboxEnforcement;
@@ -316,19 +317,22 @@ async fn run_command_under_sandbox(
}
}
// Special-case Windows sandbox: execute and exit the process to emulate inherited stdio.
// Legacy Windows sandbox sessions emulate inherited stdio and exit the process.
if let SandboxType::Windows = sandbox_type {
#[cfg(target_os = "windows")]
{
run_command_under_windows_session(
&config,
&permission_profile,
command,
cwd,
workspace_roots,
env,
)
.await;
if config.permissions.windows_sandbox_type != codex_sandboxing::SandboxType::WindowsMxc
{
run_command_under_windows_session(
&config,
&permission_profile,
command,
cwd,
workspace_roots,
env,
)
.await;
}
}
#[cfg(not(target_os = "windows"))]
{
@@ -348,6 +352,7 @@ async fn run_command_under_sandbox(
Some(spec) => Some(
spec.start_proxy(
&permission_profile,
managed_proxy_routing_for_windows_sandbox(config.permissions.windows_sandbox_type),
/*policy_decider*/ None,
/*blocked_request_observer*/ None,
managed_network_requirements_enabled,
@@ -363,7 +368,7 @@ async fn run_command_under_sandbox(
.map(codex_core::config::StartedNetworkProxy::proxy);
// Proxy containment depends on whether a proxy is active, not whether its
// policy came from managed requirements.
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "windows"))]
let enforce_managed_network = network.is_some();
let managed_mitm_ca_trust_bundle_path = match network.as_ref() {
Some(network) => network.managed_mitm_ca_trust_bundle_path(),
@@ -449,9 +454,57 @@ async fn run_command_under_sandbox(
)
.await?
}
#[cfg(not(target_os = "windows"))]
SandboxType::Windows => {
unreachable!("Windows sandbox should have been handled above");
}
#[cfg(target_os = "windows")]
SandboxType::Windows => {
use codex_sandboxing::SandboxCommand;
use codex_sandboxing::SandboxManager;
use codex_sandboxing::SandboxTransformRequest;
use codex_utils_path_uri::PathUri;
let (program, args) = command
.split_first()
.context("sandbox command must not be empty")?;
let sandbox_policy_cwd = PathUri::from_abs_path(&sandbox_policy_cwd);
let codex_self_exe = std::env::current_exe()?;
let request = SandboxManager::new().transform(SandboxTransformRequest {
command: SandboxCommand {
program: program.into(),
args: args.to_vec(),
cwd: PathUri::from_abs_path(&cwd),
env,
managed_network: None,
additional_permissions: None,
},
permissions: &runtime_permission_profile,
sandbox: codex_sandboxing::SandboxType::WindowsMxc,
enforce_managed_network,
environment_id: None,
network: network.as_ref(),
sandbox_policy_cwd: &sandbox_policy_cwd,
sandbox_exe: Some(codex_self_exe.as_path()),
use_legacy_landlock: false,
windows_sandbox_level: codex_protocol::config_types::WindowsSandboxLevel::Disabled,
windows_sandbox_private_desktop: false,
})?;
let (program, args) = request
.command
.split_first()
.context("missing MXC wrapper")?;
spawn_debug_sandbox_child(
PathBuf::from(program),
args.to_vec(),
/*arg0*/ None,
cwd.to_path_buf(),
runtime_permission_profile.network_sandbox_policy(),
request.env,
|_| {},
)
.await?
}
};
#[cfg(target_os = "macos")]
+6
View File
@@ -128,6 +128,7 @@ use codex_protocol::protocol::AskForApproval;
use codex_protocol::protocol::MultiAgentVersion;
use codex_protocol::protocol::SandboxPolicy;
use codex_rmcp_client::McpOAuthRefreshMode;
use codex_sandboxing::SandboxType;
pub use codex_thread_store::ExtraConfig;
use codex_utils_absolute_path::AbsolutePathBuf;
use codex_utils_absolute_path::AbsolutePathBufGuard;
@@ -345,6 +346,8 @@ pub struct Permissions {
/// Effective Windows sandbox mode derived from `[windows].sandbox` or
/// legacy feature keys.
pub windows_sandbox_mode: Option<WindowsSandboxModeToml>,
/// Selected Windows sandbox implementation, separate from the legacy setup level.
pub windows_sandbox_type: SandboxType,
/// Whether the final Windows sandboxed child should run on a private desktop.
pub windows_sandbox_private_desktop: bool,
}
@@ -367,6 +370,7 @@ impl Permissions {
allow_login_shell: true,
shell_environment_policy: ShellEnvironmentPolicy::default(),
windows_sandbox_mode: None,
windows_sandbox_type: SandboxType::None,
windows_sandbox_private_desktop: true,
})
}
@@ -3319,6 +3323,7 @@ impl Config {
let enable_network_proxy = features.enabled(Feature::NetworkProxy);
let PreparedWindowsSandboxConfig {
mode: windows_sandbox_mode,
sandbox_type: windows_sandbox_type,
level: windows_sandbox_level,
} = prepare_windows_sandbox_config(
resolve_windows_sandbox_mode(&cfg),
@@ -4154,6 +4159,7 @@ impl Config {
allow_login_shell,
shell_environment_policy,
windows_sandbox_mode,
windows_sandbox_type,
windows_sandbox_private_desktop,
},
explicit_permission_profile_mode,
+22 -3
View File
@@ -5,6 +5,7 @@ use codex_network_proxy::ConfigReloader;
use codex_network_proxy::ConfigReloaderFuture;
use codex_network_proxy::ConfigState;
use codex_network_proxy::EnvironmentNetworkPolicy;
use codex_network_proxy::ManagedProxyRouting;
use codex_network_proxy::NetworkDecision;
use codex_network_proxy::NetworkPolicyDecider;
use codex_network_proxy::NetworkProxy;
@@ -34,13 +35,19 @@ pub struct NetworkProxySpec {
pub struct StartedNetworkProxy {
proxy: NetworkProxy,
network_policy_decider: Option<Arc<dyn NetworkPolicyDecider>>,
_handle: NetworkProxyHandle,
}
impl StartedNetworkProxy {
fn new(proxy: NetworkProxy, handle: NetworkProxyHandle) -> Self {
fn new(
proxy: NetworkProxy,
handle: NetworkProxyHandle,
network_policy_decider: Option<Arc<dyn NetworkPolicyDecider>>,
) -> Self {
Self {
proxy,
network_policy_decider,
_handle: handle,
}
}
@@ -48,6 +55,10 @@ impl StartedNetworkProxy {
pub fn proxy(&self) -> NetworkProxy {
self.proxy.clone()
}
pub(crate) fn network_policy_decider(&self) -> Option<Arc<dyn NetworkPolicyDecider>> {
self.network_policy_decider.as_ref().map(Arc::clone)
}
}
#[derive(Clone)]
@@ -179,13 +190,17 @@ impl NetworkProxySpec {
pub async fn start_proxy(
&self,
permission_profile: &PermissionProfile,
managed_proxy_routing: ManagedProxyRouting,
policy_decider: Option<Arc<dyn NetworkPolicyDecider>>,
blocked_request_observer: Option<Arc<dyn BlockedRequestObserver>>,
enable_network_approval_flow: bool,
audit_metadata: NetworkProxyAuditMetadata,
) -> std::io::Result<StartedNetworkProxy> {
let state = self.build_state_with_audit_metadata(audit_metadata)?;
let mut builder = NetworkProxy::builder().state(Arc::new(state));
let mut builder = NetworkProxy::builder()
.state(Arc::new(state))
.managed_proxy_routing(managed_proxy_routing);
let retained_policy_decider = policy_decider.as_ref().map(Arc::clone);
if enable_network_approval_flow && !self.hard_deny_allowlist_misses {
if let Some(policy_decider) = policy_decider {
builder = builder.policy_decider_arc(policy_decider);
@@ -204,7 +219,11 @@ impl NetworkProxySpec {
.run()
.await
.map_err(|err| std::io::Error::other(format!("failed to run network proxy: {err}")))?;
Ok(StartedNetworkProxy::new(proxy, handle))
Ok(StartedNetworkProxy::new(
proxy,
handle,
retained_policy_decider,
))
}
pub(crate) fn recompute_for_permission_profile(
@@ -5,11 +5,14 @@ use super::apply_requirement_constrained_value;
use codex_config::ConstrainedWithSource;
use codex_config::types::WindowsSandboxModeToml;
use codex_protocol::config_types::WindowsSandboxLevel;
use codex_sandboxing::SandboxType;
#[derive(Debug, PartialEq)]
pub struct PreparedWindowsSandboxConfig {
/// Explicit or requirement-constrained mode; excludes feature-only fallback.
pub mode: Option<WindowsSandboxModeToml>,
/// Selected implementation, kept separate from the legacy setup level.
pub sandbox_type: SandboxType,
/// Effective sandbox level after Windows requirements have been applied.
pub level: WindowsSandboxLevel,
}
@@ -39,7 +42,16 @@ pub fn prepare_windows_sandbox_config(
Some(WindowsSandboxModeToml::Unelevated) => WindowsSandboxLevel::RestrictedToken,
None => WindowsSandboxLevel::Disabled,
};
Ok(PreparedWindowsSandboxConfig { mode, level })
let sandbox_type = if level == WindowsSandboxLevel::Disabled {
SandboxType::None
} else {
SandboxType::WindowsRestrictedToken
};
Ok(PreparedWindowsSandboxConfig {
mode,
sandbox_type,
level,
})
}
#[cfg(test)]
@@ -11,6 +11,7 @@ fn configured_mode_takes_priority_without_persisting_feature_fallback() -> std::
None,
PreparedWindowsSandboxConfig {
mode: None,
sandbox_type: SandboxType::WindowsRestrictedToken,
level: WindowsSandboxLevel::Elevated,
},
),
@@ -18,6 +19,7 @@ fn configured_mode_takes_priority_without_persisting_feature_fallback() -> std::
Some(WindowsSandboxModeToml::Unelevated),
PreparedWindowsSandboxConfig {
mode: Some(WindowsSandboxModeToml::Unelevated),
sandbox_type: SandboxType::WindowsRestrictedToken,
level: WindowsSandboxLevel::RestrictedToken,
},
),
+17 -2
View File
@@ -163,6 +163,7 @@ use codex_rollout::state_db;
use codex_rollout_trace::AgentResultTracePayload;
use codex_rollout_trace::ThreadStartedTraceMetadata;
use codex_rollout_trace::ThreadTraceContext;
use codex_sandboxing::SandboxType;
use codex_sandboxing::policy_transforms::intersect_permission_profiles_with_context;
use codex_shell_command::parse_command::parse_command;
use codex_terminal_detection::user_agent;
@@ -329,6 +330,7 @@ use crate::turn_timing::TurnTimingState;
use crate::turn_timing::record_turn_ttfm_metric;
use crate::unified_exec::UnifiedExecProcessManager;
use crate::windows_sandbox::WindowsSandboxLevelExt;
use crate::windows_sandbox::managed_proxy_routing_for_windows_sandbox;
use codex_core_plugins::PluginCommandAttribution;
use codex_core_plugins::PluginsManager;
use codex_core_plugins::RecommendedPluginCandidatesInput;
@@ -836,6 +838,7 @@ impl Session {
allow_login_shell: config.permissions.allow_login_shell,
shell_environment_policy: config.permissions.shell_environment_policy.clone(),
windows_sandbox_level: WindowsSandboxLevel::from_config(&config),
windows_sandbox_type: config.permissions.windows_sandbox_type,
windows_sandbox_private_desktop: config.permissions.windows_sandbox_private_desktop,
use_legacy_landlock: config.features.use_legacy_landlock(),
legacy_fallback_cwd: config.cwd.clone(),
@@ -1184,10 +1187,12 @@ impl Session {
)
}
#[allow(clippy::too_many_arguments)]
async fn start_managed_network_proxy(
spec: &crate::config::NetworkProxySpec,
exec_policy: &codex_execpolicy::Policy,
permission_profile: &PermissionProfile,
windows_sandbox_type: SandboxType,
network_policy_decider: Option<Arc<dyn codex_network_proxy::NetworkPolicyDecider>>,
blocked_request_observer: Option<Arc<dyn codex_network_proxy::BlockedRequestObserver>>,
managed_network_requirements_enabled: bool,
@@ -1205,6 +1210,7 @@ impl Session {
let network_proxy = spec
.start_proxy(
permission_profile,
managed_proxy_routing_for_windows_sandbox(windows_sandbox_type),
network_policy_decider,
blocked_request_observer,
managed_network_requirements_enabled,
@@ -1273,7 +1279,15 @@ impl Session {
.set_snapshot_credential_broker(SnapshotCredentialBrokerState::Inactive);
return;
}
if let Some(started_proxy) = self.services.network_proxy.load_full() {
let managed_proxy_routing =
managed_proxy_routing_for_windows_sandbox(session_configuration.windows_sandbox_type);
let started_proxy = self.services.network_proxy.load_full();
let network_policy_decider = started_proxy
.as_ref()
.and_then(|started_proxy| started_proxy.network_policy_decider());
if let Some(started_proxy) = started_proxy
&& started_proxy.proxy().managed_proxy_routing() == managed_proxy_routing
{
if let Err(err) = spec.apply_to_started_proxy(started_proxy.as_ref()).await {
warn!("failed to refresh managed network proxy for sandbox change: {err}");
} else {
@@ -1292,7 +1306,8 @@ impl Session {
&spec,
current_exec_policy.as_ref(),
&session_configuration.permission_profile(),
/*network_policy_decider*/ None,
session_configuration.windows_sandbox_type,
network_policy_decider,
Some(build_blocked_request_observer(Arc::clone(
&self.services.network_approval,
))),
+3
View File
@@ -40,6 +40,7 @@ use codex_protocol::protocol::MultiAgentVersion;
use codex_protocol::protocol::ThreadHistoryMode;
use codex_protocol::protocol::ThreadSource;
use codex_protocol::protocol::TurnEnvironmentSelections;
use codex_sandboxing::SandboxType;
use codex_skills::SkillError;
use codex_utils_git_discovery::GitRootDiscovery;
use codex_utils_path::replace_path_and_deduplicate;
@@ -119,6 +120,7 @@ pub(crate) struct SessionConfiguration {
// TODO(anp): Reconcile these legacy thread defaults with TurnEnvironment::sandbox_context;
// internal sandbox decisions should use the selected environment's configuration.
pub(super) windows_sandbox_level: WindowsSandboxLevel,
pub(super) windows_sandbox_type: SandboxType,
pub(super) windows_sandbox_private_desktop: bool,
pub(super) use_legacy_landlock: bool,
@@ -1490,6 +1492,7 @@ impl Session {
spec,
current_exec_policy.as_ref(),
config.permissions.permission_profile(),
config.permissions.windows_sandbox_type,
network_policy_decider.as_ref().map(Arc::clone),
blocked_request_observer.as_ref().map(Arc::clone),
managed_network_requirements_configured,
+35 -1
View File
@@ -132,6 +132,8 @@ use codex_history::InitialHistory;
use codex_history::ResponseItemEnvelope;
use codex_history::ResumedHistory;
use codex_history::RolloutItem;
#[cfg(windows)]
use codex_network_proxy::ManagedProxyRouting;
use codex_network_proxy::NetworkProxyConfig;
use codex_otel::MetricsClient;
use codex_otel::MetricsConfig;
@@ -1062,6 +1064,7 @@ async fn start_managed_network_proxy_applies_execpolicy_network_rules() -> anyho
&spec,
&exec_policy,
&permission_profile,
SandboxType::None,
/*network_policy_decider*/ None,
/*blocked_request_observer*/ None,
/*managed_network_requirements_enabled*/ false,
@@ -1107,6 +1110,7 @@ async fn start_managed_network_proxy_ignores_invalid_execpolicy_network_rules()
&spec,
&exec_policy,
&permission_profile,
SandboxType::None,
/*network_policy_decider*/ None,
/*blocked_request_observer*/ None,
/*managed_network_requirements_enabled*/ false,
@@ -1147,6 +1151,7 @@ async fn managed_network_proxy_decider_survives_full_access_start() -> anyhow::R
&spec,
&exec_policy,
&full_access_permission_profile,
SandboxType::None,
Some(network_policy_decider),
/*blocked_request_observer*/ None,
/*managed_network_requirements_enabled*/ true,
@@ -1219,11 +1224,14 @@ async fn new_turn_refreshes_managed_network_proxy_for_sandbox_change() -> anyhow
Some(requirements),
&initial_permission_profile,
)?;
let network_policy_decider: Arc<dyn codex_network_proxy::NetworkPolicyDecider> =
Arc::new(|_request| async { codex_network_proxy::NetworkDecision::ask("not_allowed") });
let (started_proxy, _) = Session::start_managed_network_proxy(
&spec,
&Policy::empty(),
&initial_permission_profile,
/*network_policy_decider*/ None,
SandboxType::None,
Some(Arc::clone(&network_policy_decider)),
/*blocked_request_observer*/ None,
/*managed_network_requirements_enabled*/ false,
crate::config::NetworkProxyAuditMetadata::default(),
@@ -1247,6 +1255,10 @@ async fn new_turn_refreshes_managed_network_proxy_for_sandbox_change() -> anyhow
.session_configuration
.set_permission_profile_for_tests(initial_permission_profile)
.expect("test setup should allow permission profile");
#[cfg(windows)]
{
state.session_configuration.windows_sandbox_type = SandboxType::WindowsMxc;
}
}
session
.services
@@ -1273,6 +1285,20 @@ async fn new_turn_refreshes_managed_network_proxy_for_sandbox_change() -> anyhow
started_proxy.proxy().current_cfg().await?.allowed_domains(),
Some(vec!["*.example.com".to_string()])
);
#[cfg(windows)]
{
assert_eq!(
started_proxy.proxy().managed_proxy_routing(),
ManagedProxyRouting::DedicatedListeners
);
let rebuilt_policy_decider = started_proxy
.network_policy_decider()
.expect("rebuilt managed network proxy should retain its policy decider");
assert!(Arc::ptr_eq(
&network_policy_decider,
&rebuilt_policy_decider
));
}
Ok(())
}
@@ -3945,6 +3971,7 @@ async fn set_rate_limits_retains_previous_credits() {
allow_login_shell: config.permissions.allow_login_shell,
shell_environment_policy: config.permissions.shell_environment_policy.clone(),
windows_sandbox_level: WindowsSandboxLevel::from_config(&config),
windows_sandbox_type: config.permissions.windows_sandbox_type,
windows_sandbox_private_desktop: config.permissions.windows_sandbox_private_desktop,
use_legacy_landlock: config.features.use_legacy_landlock(),
legacy_fallback_cwd: config.cwd.clone(),
@@ -4066,6 +4093,7 @@ async fn set_rate_limits_updates_plan_type_when_present() {
allow_login_shell: config.permissions.allow_login_shell,
shell_environment_policy: config.permissions.shell_environment_policy.clone(),
windows_sandbox_level: WindowsSandboxLevel::from_config(&config),
windows_sandbox_type: config.permissions.windows_sandbox_type,
windows_sandbox_private_desktop: config.permissions.windows_sandbox_private_desktop,
use_legacy_landlock: config.features.use_legacy_landlock(),
legacy_fallback_cwd: config.cwd.clone(),
@@ -4677,6 +4705,7 @@ pub(crate) async fn make_session_configuration_for_tests() -> SessionConfigurati
allow_login_shell: config.permissions.allow_login_shell,
shell_environment_policy: config.permissions.shell_environment_policy.clone(),
windows_sandbox_level: WindowsSandboxLevel::from_config(&config),
windows_sandbox_type: config.permissions.windows_sandbox_type,
windows_sandbox_private_desktop: config.permissions.windows_sandbox_private_desktop,
use_legacy_landlock: config.features.use_legacy_landlock(),
legacy_fallback_cwd: config.cwd.clone(),
@@ -5761,6 +5790,7 @@ async fn session_new_fails_when_zsh_fork_enabled_without_packaged_zsh() {
allow_login_shell: config.permissions.allow_login_shell,
shell_environment_policy: config.permissions.shell_environment_policy.clone(),
windows_sandbox_level: WindowsSandboxLevel::from_config(&config),
windows_sandbox_type: config.permissions.windows_sandbox_type,
windows_sandbox_private_desktop: config.permissions.windows_sandbox_private_desktop,
use_legacy_landlock: config.features.use_legacy_landlock(),
legacy_fallback_cwd: config.cwd.clone(),
@@ -5941,6 +5971,7 @@ pub(crate) async fn make_session_and_context() -> (Session, TurnContext) {
allow_login_shell: config.permissions.allow_login_shell,
shell_environment_policy: config.permissions.shell_environment_policy.clone(),
windows_sandbox_level: WindowsSandboxLevel::from_config(&config),
windows_sandbox_type: config.permissions.windows_sandbox_type,
windows_sandbox_private_desktop: config.permissions.windows_sandbox_private_desktop,
use_legacy_landlock: config.features.use_legacy_landlock(),
legacy_fallback_cwd: config.cwd.clone(),
@@ -6248,6 +6279,7 @@ async fn make_session_with_config_and_rx(
allow_login_shell: config.permissions.allow_login_shell,
shell_environment_policy: config.permissions.shell_environment_policy.clone(),
windows_sandbox_level: WindowsSandboxLevel::from_config(&config),
windows_sandbox_type: config.permissions.windows_sandbox_type,
windows_sandbox_private_desktop: config.permissions.windows_sandbox_private_desktop,
use_legacy_landlock: config.features.use_legacy_landlock(),
legacy_fallback_cwd: config.cwd.clone(),
@@ -6379,6 +6411,7 @@ async fn make_session_with_history_source_and_agent_control_and_rx(
allow_login_shell: config.permissions.allow_login_shell,
shell_environment_policy: config.permissions.shell_environment_policy.clone(),
windows_sandbox_level: WindowsSandboxLevel::from_config(&config),
windows_sandbox_type: config.permissions.windows_sandbox_type,
windows_sandbox_private_desktop: config.permissions.windows_sandbox_private_desktop,
use_legacy_landlock: config.features.use_legacy_landlock(),
legacy_fallback_cwd: config.cwd.clone(),
@@ -8120,6 +8153,7 @@ where
allow_login_shell: config.permissions.allow_login_shell,
shell_environment_policy: config.permissions.shell_environment_policy.clone(),
windows_sandbox_level: WindowsSandboxLevel::from_config(&config),
windows_sandbox_type: config.permissions.windows_sandbox_type,
windows_sandbox_private_desktop: config.permissions.windows_sandbox_private_desktop,
use_legacy_landlock: config.features.use_legacy_landlock(),
legacy_fallback_cwd: config.cwd.clone(),
@@ -238,6 +238,7 @@ async fn inactive_profiles_keep_snapshots_but_active_brokers_require_sandbox() -
let started_proxy = network_spec
.start_proxy(
&permission_profile,
codex_network_proxy::ManagedProxyRouting::SharedIngress,
/*policy_decider*/ None,
/*blocked_request_observer*/ None,
/*enable_network_approval_flow*/ false,
@@ -664,6 +665,7 @@ async fn snapshot_discovers_and_redacts_shell_initialized_credentials() -> Resul
let started_proxy = network_spec
.start_proxy(
&permission_profile,
codex_network_proxy::ManagedProxyRouting::SharedIngress,
/*policy_decider*/ None,
/*blocked_request_observer*/ None,
/*enable_network_approval_flow*/ false,
+11
View File
@@ -9,6 +9,7 @@ use codex_login::default_client::originator;
use codex_otel::sanitize_metric_tag_value;
use codex_protocol::config_types::WindowsSandboxLevel;
use codex_protocol::models::PermissionProfile;
use codex_sandboxing::SandboxType;
use codex_utils_absolute_path::AbsolutePathBuf;
use std::collections::BTreeMap;
use std::collections::HashMap;
@@ -16,6 +17,16 @@ use std::path::Path;
use std::path::PathBuf;
use std::time::Instant;
pub fn managed_proxy_routing_for_windows_sandbox(
sandbox_type: SandboxType,
) -> codex_network_proxy::ManagedProxyRouting {
if cfg!(windows) && sandbox_type == SandboxType::WindowsMxc {
codex_network_proxy::ManagedProxyRouting::DedicatedListeners
} else {
codex_network_proxy::ManagedProxyRouting::SharedIngress
}
}
pub trait WindowsSandboxLevelExt {
fn from_config(config: &Config) -> WindowsSandboxLevel;
fn from_features(features: &Features) -> WindowsSandboxLevel;
+4
View File
@@ -881,6 +881,10 @@ impl NetworkProxy {
self.http_addr
}
pub fn managed_proxy_routing(&self) -> ManagedProxyRouting {
self.managed_proxy_routing
}
pub fn socks_addr(&self) -> SocketAddr {
#[cfg(target_os = "windows")]
if let Some(runtime) = self.windows_runtime.as_ref() {