mirror of
https://github.com/openai/codex.git
synced 2026-11-13 06:45:07 +00:00
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:
1 parent
dfd2d8133c
commit
999a715089
40 files changed
+2792
-191
No files matched your search
+47
-14
@@ -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());
|
||||
|
||||
Reference in new issue
Block a user