mirror of
https://github.com/openai/codex.git
synced 2026-04-28 02:11:08 +03:00
Gate network proxy behind feature flag
This commit is contained in:
@@ -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#"
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user