mirror of
https://github.com/openai/codex.git
synced 2026-11-02 19:43:24 +00:00
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:
Generated
+1
@@ -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,
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
),
|
||||
|
||||
@@ -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,
|
||||
))),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user