feat(windows-sandbox): add network proxy support (#12220)

## Summary

This PR makes Windows sandbox proxying enforceable by routing proxy-only
runs through the existing `offline` sandbox user and reserving direct
network access for the existing `online` sandbox user.

In brief:

- if a Windows sandbox run should be proxy-enforced, we run it as the
`offline` user
- the `offline` user gets firewall rules that block direct outbound
traffic and only permit the configured localhost proxy path
- if a Windows sandbox run should have true direct network access, we
run it as the `online` user
- no new sandbox identity is introduced

This brings Windows in line with the intended model: proxy use is not
just env-based, it is backed by OS-level egress controls. Windows
already has two sandbox identities:

- `offline`: intended to have no direct network egress
- `online`: intended to have full network access

This PR makes proxy-enforced runs use that model directly.

### Proxy-enforced runs

When proxy enforcement is active:

- the run is assigned to the `offline` identity
- setup extracts the loopback proxy ports from the sandbox env
- Windows setup programs firewall rules for the `offline` user that:
  - block all non-loopback outbound traffic
  - block loopback UDP
  - block loopback TCP except for the configured proxy ports
- optionally allow broader localhost access when `allow_local_binding=1`

So the sandboxed process can only talk to the local proxy. It cannot
open direct outbound sockets or do local UDP-based DNS on its own.The
proxy then performs the real outbound network access outside that
restricted sandbox identity.

### Direct-network runs

When proxy enforcement is not active and full network access is allowed:

- the run is assigned to the `online` identity
- no proxy-only firewall restrictions are applied
- the process gets normal direct network access

### Unelevated vs elevated

The restricted-token / unelevated path cannot enforce per-identity
firewall policy by itself.

So for Windows proxy-enforced runs, we transparently use the logon-user
sandbox path under the hood, even if the caller started from the
unelevated mode. That keeps enforcement real instead of best-effort.

---------

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
viyatb-oai
2026-03-26 17:27:38 -07:00
committed by GitHub
parent e6e2999209
commit 81fa04783a
12 changed files with 1032 additions and 216 deletions

View File

@@ -478,7 +478,11 @@ async fn exec_windows_sandbox(
})?;
let command_path = command.first().cloned();
let sandbox_level = windows_sandbox_level;
let use_elevated = matches!(sandbox_level, WindowsSandboxLevel::Elevated);
let proxy_enforced = network.is_some();
// Windows firewall enforcement is tied to the logon-user sandbox identities, so
// proxy-enforced sessions must use that backend even when the configured mode is
// the default restricted-token sandbox.
let use_elevated = proxy_enforced || matches!(sandbox_level, WindowsSandboxLevel::Elevated);
let additional_deny_write_paths = windows_restricted_token_filesystem_overlay
.map(|overlay| {
overlay
@@ -491,14 +495,17 @@ async fn exec_windows_sandbox(
let spawn_res = tokio::task::spawn_blocking(move || {
if use_elevated {
run_windows_sandbox_capture_elevated(
policy_str.as_str(),
&sandbox_cwd,
codex_home.as_ref(),
command,
&cwd,
env,
timeout_ms,
windows_sandbox_private_desktop,
codex_windows_sandbox::ElevatedSandboxCaptureRequest {
policy_json_or_preset: policy_str.as_str(),
sandbox_policy_cwd: &sandbox_cwd,
codex_home: codex_home.as_ref(),
command,
cwd: &cwd,
env_map: env,
timeout_ms,
use_private_desktop: windows_sandbox_private_desktop,
proxy_enforced,
},
)
} else {
run_windows_sandbox_capture_with_extra_deny_write_paths(

View File

@@ -180,13 +180,15 @@ pub fn run_elevated_setup(
codex_home: &Path,
) -> anyhow::Result<()> {
codex_windows_sandbox::run_elevated_setup(
policy,
policy_cwd,
command_cwd,
env_map,
codex_home,
/*read_roots_override*/ None,
/*write_roots_override*/ None,
codex_windows_sandbox::SandboxSetupRequest {
policy,
policy_cwd,
command_cwd,
env_map,
codex_home,
proxy_enforced: false,
},
codex_windows_sandbox::SetupRootOverrides::default(),
)
}
@@ -234,6 +236,7 @@ pub fn run_setup_refresh_with_extra_read_roots(
env_map,
codex_home,
extra_read_roots,
/*proxy_enforced*/ false,
)
}