Route Windows sandbox proxy traffic by restricting SID (#34613)

## Why

Elevated Windows sandboxes need stable managed-proxy ports while preserving the network policy and environment attribution of each sandboxed process.

## What changed

- Keep shared HTTP and SOCKS5 loopback ingress listeners alive across managed-proxy instances.
- Add a per-route restricting SID to elevated sandbox tokens and dispatch incoming connections to the matching proxy policy after attributing the client process.
- Reject connections without exactly one registered route, remove routes when their proxy handle is dropped, and keep unsandboxed Windows launches off the managed ingress.
- Provision the elevated sandbox with the configured proxy ports and local-binding setting, honoring the selected profile and CLI overrides.

## Testing

- Add Windows unit tests for TCP ownership attribution, route selection, restricting-token propagation, and setup settings.
- Add an end-to-end Windows test covering stable ports, isolated environment policies, HTTP and SOCKS5 routing, and route teardown.

GitOrigin-RevId: 783fac6e0f904dc9bb1955b75d4a5895e8bb9690
This commit is contained in:
iceweasel-oai
2026-07-21 21:06:04 +00:00
committed by copyberry
parent dfd2d8133c
commit 999a715089
40 changed files with 2792 additions and 191 deletions
+1
View File
@@ -488,6 +488,7 @@ async fn run_command_under_windows_session(
windows_sandbox_level: WindowsSandboxLevel::from_config(config),
proxy_settings_mode: WindowsSandboxProxySettingsMode::Reconcile,
proxy_enforced: false,
network_proxy_restricting_sid: None,
timeout_ms: None,
read_roots_override: None,
read_roots_include_platform_defaults: false,
+47 -14
View File
@@ -1445,6 +1445,14 @@ async fn cli_main(
.await?;
}
Some(Subcommand::Sandbox(mut sandbox_cli)) => {
let config_profile = sandbox_cli
.config_profile
.as_ref()
.or(interactive.config_profile_v2.as_ref());
prepend_config_flags(
&mut sandbox_cli.config_overrides,
root_config_overrides.clone(),
);
#[cfg(target_os = "windows")]
if let Some(setup_cli) = sandbox_setup::parse_setup_command(&sandbox_cli.command)? {
reject_remote_mode_for_subcommand(
@@ -1452,7 +1460,11 @@ async fn cli_main(
root_remote_auth_token_env.as_deref(),
"sandbox setup",
)?;
sandbox_setup::run(setup_cli).await?;
let cli_overrides = sandbox_cli
.config_overrides
.parse_overrides()
.map_err(anyhow::Error::msg)?;
sandbox_setup::run(setup_cli, config_profile.cloned(), cli_overrides).await?;
return Ok(());
}
reject_remote_mode_for_subcommand(
@@ -1460,15 +1472,7 @@ async fn cli_main(
root_remote_auth_token_env.as_deref(),
"sandbox",
)?;
let config_profile = sandbox_cli
.config_profile
.as_ref()
.or(interactive.config_profile_v2.as_ref());
let loader_overrides = loader_overrides_for_profile(config_profile)?;
prepend_config_flags(
&mut sandbox_cli.config_overrides,
root_config_overrides.clone(),
);
#[cfg(target_os = "macos")]
codex_cli::run_command_under_seatbelt(
sandbox_cli,
@@ -1879,16 +1883,29 @@ fn loader_overrides_for_profile(
match profile_v2 {
Some(profile_v2) => {
let codex_home = find_codex_home()?;
Ok(LoaderOverrides {
user_config_path: Some(resolve_profile_v2_config_path(&codex_home, profile_v2)),
user_config_profile: Some(profile_v2.clone()),
..Default::default()
})
Ok(loader_overrides_for_profile_at_codex_home(
Some(profile_v2),
&codex_home,
))
}
None => Ok(LoaderOverrides::default()),
}
}
fn loader_overrides_for_profile_at_codex_home(
profile_v2: Option<&ProfileV2Name>,
codex_home: &std::path::Path,
) -> LoaderOverrides {
match profile_v2 {
Some(profile_v2) => LoaderOverrides {
user_config_path: Some(resolve_profile_v2_config_path(codex_home, profile_v2)),
user_config_profile: Some(profile_v2.clone()),
..Default::default()
},
None => LoaderOverrides::default(),
}
}
fn maybe_print_under_development_feature_warning(codex_home: &std::path::Path, feature: &str) {
let Some(spec) = FEATURES.iter().find(|spec| spec.key == feature) else {
return;
@@ -2706,6 +2723,22 @@ mod tests {
Ok(profile_v2_for_subcommand(&cli.interactive, subcommand)?.map(ToString::to_string))
}
#[test]
fn profile_loader_overrides_use_explicit_codex_home() -> anyhow::Result<()> {
let codex_home = tempfile::tempdir()?;
let profile: ProfileV2Name = "work".parse()?;
let overrides =
loader_overrides_for_profile_at_codex_home(Some(&profile), codex_home.path());
assert_eq!(
overrides.user_config_path,
Some(resolve_profile_v2_config_path(codex_home.path(), &profile))
);
assert_eq!(overrides.user_config_profile, Some(profile));
Ok(())
}
#[test]
fn profile_v2_is_rejected_for_config_management_subcommands() {
assert!(profile_v2_for_args(&["codex", "--profile", "work", "features", "list"]).is_err());
+27 -3
View File
@@ -1,10 +1,14 @@
use std::path::PathBuf;
use anyhow::Context;
use clap::ArgAction;
use clap::ArgGroup;
use clap::Parser;
use codex_core::config::ConfigBuilder;
use codex_core::config::edit::ConfigEditsBuilder;
use codex_core::config::find_codex_home;
use codex_utils_cli::ProfileV2Name;
use toml::Value as TomlValue;
#[derive(Debug, Parser)]
#[command(group(
@@ -54,9 +58,13 @@ impl SandboxSetupCommand {
}
}
pub(crate) async fn run(cmd: SandboxSetupCommand) -> anyhow::Result<()> {
pub(crate) async fn run(
cmd: SandboxSetupCommand,
config_profile: Option<ProfileV2Name>,
cli_overrides: Vec<(String, TomlValue)>,
) -> anyhow::Result<()> {
match cmd.setup_level()? {
SandboxSetupLevel::Elevated => run_elevated(cmd).await,
SandboxSetupLevel::Elevated => run_elevated(cmd, config_profile, cli_overrides).await,
}
}
@@ -75,12 +83,28 @@ pub(crate) fn parse_setup_command(
.map_err(anyhow::Error::from)
}
async fn run_elevated(cmd: SandboxSetupCommand) -> anyhow::Result<()> {
async fn run_elevated(
cmd: SandboxSetupCommand,
config_profile: Option<ProfileV2Name>,
cli_overrides: Vec<(String, TomlValue)>,
) -> anyhow::Result<()> {
let identity = resolve_sandbox_setup_identity(&cmd)?;
let config = ConfigBuilder::default()
.codex_home(identity.codex_home.clone())
.fallback_cwd(Some(identity.codex_home.clone()))
.loader_overrides(super::loader_overrides_for_profile_at_codex_home(
config_profile.as_ref(),
&identity.codex_home,
))
.cli_overrides(cli_overrides)
.build()
.await
.context("failed to load target user's Codex config for sandbox provisioning")?;
codex_core::windows_sandbox::run_elevated_provisioning_setup(
identity.codex_home.as_path(),
identity.real_user.as_str(),
config.permissions.network.as_ref(),
)?;
ConfigEditsBuilder::new(identity.codex_home.as_path())
.set_windows_sandbox_mode("elevated")