Gate network proxy behind feature flag

This commit is contained in:
viyatb-oai
2025-12-21 12:03:20 -08:00
parent a575da87c4
commit acb1767588
7 changed files with 69 additions and 3 deletions

View File

@@ -1197,7 +1197,10 @@ impl Config {
|| config_profile.sandbox_mode.is_some()
|| cfg.sandbox_mode.is_some();
let network_proxy = resolve_network_proxy_config(&cfg, &codex_home);
let mut network_proxy = resolve_network_proxy_config(&cfg, &codex_home);
if !features.enabled(Feature::NetworkProxy) {
network_proxy.enabled = false;
}
let mut model_providers = built_in_model_providers();
// Merge user-defined providers into the built-in list.
@@ -1556,6 +1559,51 @@ persistence = "none"
);
}
#[test]
fn network_proxy_is_rollout_gated_by_feature_flag() -> std::io::Result<()> {
let cfg_without_feature_flag = r#"
[network_proxy]
enabled = true
"#;
let parsed_without_feature_flag =
toml::from_str::<ConfigToml>(cfg_without_feature_flag).expect("TOML parse should work");
let cwd_temp_dir = TempDir::new().unwrap();
std::fs::write(cwd_temp_dir.path().join(".git"), "gitdir: nowhere")?;
let codex_home_temp_dir = TempDir::new().unwrap();
let config_without_feature_flag = Config::load_from_base_config_with_overrides(
parsed_without_feature_flag,
ConfigOverrides {
cwd: Some(cwd_temp_dir.path().to_path_buf()),
..Default::default()
},
codex_home_temp_dir.path().to_path_buf(),
)?;
assert!(!config_without_feature_flag.network_proxy.enabled);
let cfg_with_feature_flag = r#"
[features]
network_proxy = true
[network_proxy]
enabled = true
"#;
let parsed_with_feature_flag =
toml::from_str::<ConfigToml>(cfg_with_feature_flag).expect("TOML parse should work");
let cwd_temp_dir = TempDir::new().unwrap();
std::fs::write(cwd_temp_dir.path().join(".git"), "gitdir: nowhere")?;
let codex_home_temp_dir = TempDir::new().unwrap();
let config_with_feature_flag = Config::load_from_base_config_with_overrides(
parsed_with_feature_flag,
ConfigOverrides {
cwd: Some(cwd_temp_dir.path().to_path_buf()),
..Default::default()
},
codex_home_temp_dir.path().to_path_buf(),
)?;
assert!(config_with_feature_flag.network_proxy.enabled);
Ok(())
}
#[test]
fn tui_config_missing_notifications_field_defaults_to_enabled() {
let cfg = r#"

View File

@@ -85,6 +85,8 @@ pub enum Feature {
ShellSnapshot,
/// Experimental TUI v2 (viewport) implementation.
Tui2,
/// Route subprocess network access through the Codex network proxy and surface approvals.
NetworkProxy,
}
impl Feature {
@@ -405,4 +407,10 @@ pub const FEATURES: &[FeatureSpec] = &[
stage: Stage::Experimental,
default_enabled: false,
},
FeatureSpec {
id: Feature::NetworkProxy,
key: "network_proxy",
stage: Stage::Experimental,
default_enabled: false,
},
];

View File

@@ -354,6 +354,9 @@ Though using this option may also be necessary if you try to use Codex in enviro
Codex can route subprocess network traffic through an external proxy (for example, the `network_proxy` sandbox proxy) and surface approval prompts when requests are blocked by policy.
```toml
[features]
network_proxy = true
[network_proxy]
enabled = true
proxy_url = "http://127.0.0.1:3128"
@@ -376,6 +379,7 @@ poll_interval_ms = 1000
Notes:
- Proxy settings are injected only when sandbox network access is enabled (or full access mode). If the sandbox blocks network access, requests are blocked at the OS layer.
- Network proxy integration is rollout-gated behind `[features].network_proxy = true`.
- `proxy_url` is used for HTTP proxy envs (`HTTP_PROXY`, `HTTPS_PROXY`, `http_proxy`, `https_proxy`, plus npm/yarn variants). Docker and Cloud SDK proxy envs are derived from the HTTP proxy when present.
- When `proxy_url` points at localhost, Codex also assumes a SOCKS5 proxy on `localhost:8081` for `ALL_PROXY`, `GRPC_PROXY`, `FTP_PROXY`, `RSYNC_PROXY`, and (macOS only) `GIT_SSH_COMMAND`.
- `no_proxy` entries bypass the proxy; defaults include localhost + private network ranges. Use sparingly because bypassed traffic is not filtered by the proxy policy.

View File

@@ -105,6 +105,7 @@ exclude_slash_tmp = false
[network_proxy]
# Enable proxy env injection + approval prompts for blocked domains. Default: false
# NOTE: This is rollout-gated behind `[features].network_proxy = true`.
enabled = false
# HTTP/HTTPS proxy URL. Default: "http://127.0.0.1:3128"
proxy_url = "http://127.0.0.1:3128"
@@ -259,6 +260,7 @@ rmcp_client = false
apply_patch_freeform = false
view_image_tool = true
web_search_request = false
network_proxy = false
ghost_commit = false
enable_experimental_windows_sandbox = false
skills = false

View File

@@ -47,6 +47,7 @@ The proxy reads `~/.codex/config.toml`:
- `[network_proxy]` for endpoints, mode, and toggles.
- `[network_proxy.policy]` for `allowed_domains` / `denied_domains` (and, on macOS, optional local IPC allowances).
- `[network_proxy.mitm]` for MITM CA paths and inspection settings.
- Codex integration is rollout-gated behind `[features].network_proxy = true`.
Codex is the source of truth. Approval actions update the config and trigger a proxy reload.

View File

@@ -22,6 +22,9 @@ cargo build -p codex-network-proxy --features mitm
Add this to `~/.codex/config.toml`:
```toml
[features]
network_proxy = true
[network_proxy]
enabled = true
proxy_url = "http://127.0.0.1:3128"
@@ -95,6 +98,6 @@ curl -fsS -X POST http://127.0.0.1:8080/mode -d '{"mode":"full"}'
## Codex integration sanity check
1) Start the proxy.
2) Launch Codex with the proxy enabled in config.
2) Launch Codex with `[features].network_proxy = true` and `network_proxy.enabled = true` set in config.
3) Run a network command (e.g., `curl https://example.com`).
4) Confirm you see the allow/deny prompt and that the proxy logs reflect the decision.

View File

@@ -61,7 +61,7 @@ Codex can optionally route outbound network traffic through a proxy and prompt y
Key behaviors:
- The OS sandbox is still the first line of defense. If network access is disabled, outbound requests are blocked at the OS level.
- When network is enabled and `network_proxy.enabled = true`, Codex polls the proxy admin API (`/blocked`) and immediately notifies you about blocked domains.
- When network is enabled and both `[features].network_proxy = true` and `network_proxy.enabled = true`, Codex polls the proxy admin API (`/blocked`) and immediately notifies you about blocked domains.
- For exec commands that include HTTP/HTTPS URLs, Codex preflights the host against the proxy config and prompts before running the command.
- Approvals update `~/.codex/config.toml` under `[network_proxy.policy]` and trigger a proxy reload.
- You can choose to: