From a26207bc616fdb7429f762354e0b400cc6acd5f7 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Sun, 8 Feb 2026 13:31:38 -0800 Subject: [PATCH] feat: include NetworkConfig through ExecParams --- MODULE.bazel.lock | 3 -- codex-rs/Cargo.lock | 5 +-- codex-rs/Cargo.toml | 1 + .../app-server/src/codex_message_processor.rs | 1 + codex-rs/core/Cargo.toml | 1 + codex-rs/core/src/codex.rs | 2 ++ codex-rs/core/src/config/mod.rs | 9 ++++++ codex-rs/core/src/exec.rs | 24 +++++++++++--- codex-rs/core/src/sandboxing/mod.rs | 4 ++- codex-rs/core/src/tasks/user_shell.rs | 11 +++++-- codex-rs/core/src/tools/handlers/shell.rs | 4 +++ .../core/src/tools/runtimes/apply_patch.rs | 2 +- codex-rs/core/src/tools/runtimes/shell.rs | 16 +++++++--- .../core/src/tools/runtimes/unified_exec.rs | 30 ++++------------- .../core/src/unified_exec/process_manager.rs | 13 ++++---- codex-rs/core/tests/suite/exec.rs | 1 + .../exec-server/src/posix/escalate_server.rs | 1 + .../linux-sandbox/tests/suite/landlock.rs | 2 ++ codex-rs/network-proxy/src/proxy.rs | 32 +++++++++++++++++++ 19 files changed, 114 insertions(+), 48 deletions(-) diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 21d30454c3..15bfd9d868 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -141,8 +141,6 @@ "https://bcr.bazel.build/modules/rules_cc/0.2.16/source.json": "d03d5cde49376d87e14ec14b666c56075e5e3926930327fd5d0484a1ff2ac1cc", "https://bcr.bazel.build/modules/rules_cc/0.2.4/MODULE.bazel": "1ff1223dfd24f3ecf8f028446d4a27608aa43c3f41e346d22838a4223980b8cc", "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642", - "https://bcr.bazel.build/modules/rules_foreign_cc/0.15.1/MODULE.bazel": "c2c60d26c79fda484acb95cdbec46e89d6b28b4845cb277160ce1e0c8622bb88", - "https://bcr.bazel.build/modules/rules_foreign_cc/0.15.1/source.json": "a161811a63ba8a859086da3b7ff3ad04f2e9c255d7727b41087103fc0eb22f55", "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", @@ -191,7 +189,6 @@ "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937", "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", - "https://bcr.bazel.build/modules/rules_python/1.2.0/MODULE.bazel": "5aeeb48b2a6c19d668b48adf2b8a2b209a6310c230db0ce77450f148a89846e4", "https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13", "https://bcr.bazel.build/modules/rules_python/1.4.1/MODULE.bazel": "8991ad45bdc25018301d6b7e1d3626afc3c8af8aaf4bc04f23d0b99c938b73a6", "https://bcr.bazel.build/modules/rules_python/1.6.0/MODULE.bazel": "7e04ad8f8d5bea40451cf80b1bd8262552aa73f841415d20db96b7241bd027d8", diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index e2b13f91e7..c476c4b3ce 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -1565,6 +1565,7 @@ dependencies = [ "codex-file-search", "codex-git", "codex-keyring-store", + "codex-network-proxy", "codex-otel", "codex-protocol", "codex-rmcp-client", @@ -1901,9 +1902,8 @@ dependencies = [ "anyhow", "async-trait", "clap", - "codex-app-server-protocol", - "codex-core", "codex-utils-absolute-path", + "codex-utils-home-dir", "globset", "pretty_assertions", "rama-core", @@ -1919,6 +1919,7 @@ dependencies = [ "tempfile", "time", "tokio", + "toml 0.9.11+spec-1.1.0", "tracing", "tracing-subscriber", "url", diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index 2cfcf59ef8..10e3b122aa 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -93,6 +93,7 @@ codex-linux-sandbox = { path = "linux-sandbox" } codex-lmstudio = { path = "lmstudio" } codex-login = { path = "login" } codex-mcp-server = { path = "mcp-server" } +codex-network-proxy = { path = "network-proxy" } codex-ollama = { path = "ollama" } codex-otel = { path = "otel" } codex-process-hardening = { path = "process-hardening" } diff --git a/codex-rs/app-server/src/codex_message_processor.rs b/codex-rs/app-server/src/codex_message_processor.rs index 3f65cf2879..10d534a7db 100644 --- a/codex-rs/app-server/src/codex_message_processor.rs +++ b/codex-rs/app-server/src/codex_message_processor.rs @@ -1628,6 +1628,7 @@ impl CodexMessageProcessor { cwd, expiration: timeout_ms.into(), env, + network: self.config.network.clone(), sandbox_permissions: SandboxPermissions::UseDefault, windows_sandbox_level, justification: None, diff --git a/codex-rs/core/Cargo.toml b/codex-rs/core/Cargo.toml index d686343ae7..b388463151 100644 --- a/codex-rs/core/Cargo.toml +++ b/codex-rs/core/Cargo.toml @@ -35,6 +35,7 @@ codex-execpolicy = { workspace = true } codex-file-search = { workspace = true } codex-git = { workspace = true } codex-keyring-store = { workspace = true } +codex-network-proxy = { workspace = true } codex-otel = { workspace = true } codex-protocol = { workspace = true } codex-rmcp-client = { workspace = true } diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index 8280b5a9e0..37d48848bf 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -6658,6 +6658,7 @@ mod tests { cwd: turn_context.cwd.clone(), expiration: timeout_ms.into(), env: HashMap::new(), + network: None, sandbox_permissions, windows_sandbox_level: turn_context.windows_sandbox_level, justification: Some("test".to_string()), @@ -6670,6 +6671,7 @@ mod tests { cwd: params.cwd.clone(), expiration: timeout_ms.into(), env: HashMap::new(), + network: None, windows_sandbox_level: turn_context.windows_sandbox_level, justification: params.justification.clone(), arg0: None, diff --git a/codex-rs/core/src/config/mod.rs b/codex-rs/core/src/config/mod.rs index dee21376cb..34a1772266 100644 --- a/codex-rs/core/src/config/mod.rs +++ b/codex-rs/core/src/config/mod.rs @@ -47,6 +47,7 @@ use crate::protocol::SandboxPolicy; use crate::windows_sandbox::WindowsSandboxLevelExt; use codex_app_server_protocol::Tools; use codex_app_server_protocol::UserSavedConfig; +use codex_network_proxy::NetworkProxy; use codex_protocol::config_types::AltScreenMode; use codex_protocol::config_types::ForcedLoginMethod; use codex_protocol::config_types::ModeKind; @@ -152,6 +153,9 @@ pub struct Config { /// using backend-specific headers or URLs to enforce this. pub enforce_residency: Constrained>, + /// Effective network configuration applied to all spawned processes. + pub network: Option, + /// True if the user passed in an override or set a value in config.toml /// for either of approval_policy or sandbox_mode. pub did_user_set_custom_approval_policy_or_sandbox_mode: bool, @@ -1690,6 +1694,7 @@ impl Config { approval_policy: constrained_approval_policy.value, sandbox_policy: constrained_sandbox_policy.value, enforce_residency: enforce_residency.value, + network: None, did_user_set_custom_approval_policy_or_sandbox_mode, forced_auto_mode_downgraded_on_windows, shell_environment_policy, @@ -4003,6 +4008,7 @@ model_verbosity = "high" approval_policy: Constrained::allow_any(AskForApproval::Never), sandbox_policy: Constrained::allow_any(SandboxPolicy::new_read_only_policy()), enforce_residency: Constrained::allow_any(None), + network: None, did_user_set_custom_approval_policy_or_sandbox_mode: true, forced_auto_mode_downgraded_on_windows: false, shell_environment_policy: ShellEnvironmentPolicy::default(), @@ -4091,6 +4097,7 @@ model_verbosity = "high" approval_policy: Constrained::allow_any(AskForApproval::UnlessTrusted), sandbox_policy: Constrained::allow_any(SandboxPolicy::new_read_only_policy()), enforce_residency: Constrained::allow_any(None), + network: None, did_user_set_custom_approval_policy_or_sandbox_mode: true, forced_auto_mode_downgraded_on_windows: false, shell_environment_policy: ShellEnvironmentPolicy::default(), @@ -4194,6 +4201,7 @@ model_verbosity = "high" approval_policy: Constrained::allow_any(AskForApproval::OnFailure), sandbox_policy: Constrained::allow_any(SandboxPolicy::new_read_only_policy()), enforce_residency: Constrained::allow_any(None), + network: None, did_user_set_custom_approval_policy_or_sandbox_mode: true, forced_auto_mode_downgraded_on_windows: false, shell_environment_policy: ShellEnvironmentPolicy::default(), @@ -4283,6 +4291,7 @@ model_verbosity = "high" approval_policy: Constrained::allow_any(AskForApproval::OnFailure), sandbox_policy: Constrained::allow_any(SandboxPolicy::new_read_only_policy()), enforce_residency: Constrained::allow_any(None), + network: None, did_user_set_custom_approval_policy_or_sandbox_mode: true, forced_auto_mode_downgraded_on_windows: false, shell_environment_policy: ShellEnvironmentPolicy::default(), diff --git a/codex-rs/core/src/exec.rs b/codex-rs/core/src/exec.rs index d4d508ced6..2475b16928 100644 --- a/codex-rs/core/src/exec.rs +++ b/codex-rs/core/src/exec.rs @@ -32,6 +32,7 @@ use crate::sandboxing::SandboxPermissions; use crate::spawn::StdioPolicy; use crate::spawn::spawn_child_async; use crate::text_encoding::bytes_to_string_smart; +use codex_network_proxy::NetworkProxy; use codex_utils_pty::process_group::kill_child_process_group; pub const DEFAULT_EXEC_COMMAND_TIMEOUT_MS: u64 = 10_000; @@ -63,6 +64,7 @@ pub struct ExecParams { pub cwd: PathBuf, pub expiration: ExecExpiration, pub env: HashMap, + pub network: Option, pub sandbox_permissions: SandboxPermissions, pub windows_sandbox_level: codex_protocol::config_types::WindowsSandboxLevel, pub justification: Option, @@ -170,13 +172,13 @@ pub async fn process_exec_tool_call( command, cwd, expiration, - env, + mut env, + network, sandbox_permissions, windows_sandbox_level, justification, arg0: _, } = params; - let (program, args) = command.split_first().ok_or_else(|| { CodexErr::Io(io::Error::new( io::ErrorKind::InvalidInput, @@ -208,13 +210,14 @@ pub async fn process_exec_tool_call( .map_err(CodexErr::from)?; // Route through the sandboxing module for a single, unified execution path. - crate::sandboxing::execute_env(exec_env, sandbox_policy, stdout_stream).await + crate::sandboxing::execute_env(exec_env, sandbox_policy, stdout_stream, network).await } pub(crate) async fn execute_exec_env( env: ExecEnv, sandbox_policy: &SandboxPolicy, stdout_stream: Option, + network: Option, ) -> Result { let ExecEnv { command, @@ -233,6 +236,7 @@ pub(crate) async fn execute_exec_env( cwd, expiration, env, + network, sandbox_permissions, windows_sandbox_level, justification, @@ -324,11 +328,15 @@ async fn exec_windows_sandbox( let ExecParams { command, cwd, - env, + mut env, + network, expiration, windows_sandbox_level, .. } = params; + if let Some(network) = network.as_ref() { + network.apply_to_env(&mut env); + } // TODO(iceweasel-oai): run_windows_sandbox_capture should support all // variants of ExecExpiration, not just timeout. let timeout_ms = expiration.timeout_ms(); @@ -677,12 +685,16 @@ async fn exec( let ExecParams { command, cwd, - env, + mut env, + network, arg0, expiration, windows_sandbox_level: _, .. } = params; + if let Some(network) = network.as_ref() { + network.apply_to_env(&mut env); + } let (program, args) = command.split_first().ok_or_else(|| { CodexErr::Io(io::Error::new( @@ -1061,6 +1073,7 @@ mod tests { cwd: std::env::current_dir()?, expiration: 500.into(), env, + network: None, sandbox_permissions: SandboxPermissions::UseDefault, windows_sandbox_level: codex_protocol::config_types::WindowsSandboxLevel::Disabled, justification: None, @@ -1107,6 +1120,7 @@ mod tests { cwd: cwd.clone(), expiration: ExecExpiration::Cancellation(cancel_token), env, + network: None, sandbox_permissions: SandboxPermissions::UseDefault, windows_sandbox_level: codex_protocol::config_types::WindowsSandboxLevel::Disabled, justification: None, diff --git a/codex-rs/core/src/sandboxing/mod.rs b/codex-rs/core/src/sandboxing/mod.rs index bc914abe5b..3cad82fec8 100644 --- a/codex-rs/core/src/sandboxing/mod.rs +++ b/codex-rs/core/src/sandboxing/mod.rs @@ -21,6 +21,7 @@ use crate::seatbelt::create_seatbelt_command_args; use crate::spawn::CODEX_SANDBOX_ENV_VAR; use crate::spawn::CODEX_SANDBOX_NETWORK_DISABLED_ENV_VAR; use crate::tools::sandboxing::SandboxablePreference; +use codex_network_proxy::NetworkProxy; use codex_protocol::config_types::WindowsSandboxLevel; pub use codex_protocol::models::SandboxPermissions; use std::collections::HashMap; @@ -207,6 +208,7 @@ pub async fn execute_env( env: ExecEnv, policy: &SandboxPolicy, stdout_stream: Option, + network: Option, ) -> crate::error::Result { - execute_exec_env(env, policy, stdout_stream).await + execute_exec_env(env, policy, stdout_stream, network).await } diff --git a/codex-rs/core/src/tasks/user_shell.rs b/codex-rs/core/src/tasks/user_shell.rs index d626057d92..0ee65eacea 100644 --- a/codex-rs/core/src/tasks/user_shell.rs +++ b/codex-rs/core/src/tasks/user_shell.rs @@ -160,9 +160,14 @@ pub(crate) async fn execute_user_shell_command( }); let sandbox_policy = SandboxPolicy::DangerFullAccess; - let exec_result = execute_exec_env(exec_env, &sandbox_policy, stdout_stream) - .or_cancel(&cancellation_token) - .await; + let exec_result = execute_exec_env( + exec_env, + &sandbox_policy, + stdout_stream, + turn_context.config.network.clone(), + ) + .or_cancel(&cancellation_token) + .await; match exec_result { Err(CancelErr::Cancelled) => { diff --git a/codex-rs/core/src/tools/handlers/shell.rs b/codex-rs/core/src/tools/handlers/shell.rs index 1d4f01356f..fd678c3a3c 100644 --- a/codex-rs/core/src/tools/handlers/shell.rs +++ b/codex-rs/core/src/tools/handlers/shell.rs @@ -53,6 +53,7 @@ impl ShellHandler { cwd: turn_context.resolve_path(params.workdir.clone()), expiration: params.timeout_ms.into(), env: create_env(&turn_context.shell_environment_policy, Some(thread_id)), + network: turn_context.config.network.clone(), sandbox_permissions: params.sandbox_permissions.unwrap_or_default(), windows_sandbox_level: turn_context.windows_sandbox_level, justification: params.justification.clone(), @@ -81,6 +82,7 @@ impl ShellCommandHandler { cwd: turn_context.resolve_path(params.workdir.clone()), expiration: params.timeout_ms.into(), env: create_env(&turn_context.shell_environment_policy, Some(thread_id)), + network: turn_context.config.network.clone(), sandbox_permissions: params.sandbox_permissions.unwrap_or_default(), windows_sandbox_level: turn_context.windows_sandbox_level, justification: params.justification.clone(), @@ -311,6 +313,7 @@ impl ShellHandler { cwd: exec_params.cwd.clone(), timeout_ms: exec_params.expiration.timeout_ms(), env: exec_params.env.clone(), + network: exec_params.network.clone(), sandbox_permissions: exec_params.sandbox_permissions, justification: exec_params.justification.clone(), exec_approval_requirement, @@ -441,6 +444,7 @@ mod tests { assert_eq!(exec_params.command, expected_command); assert_eq!(exec_params.cwd, expected_cwd); assert_eq!(exec_params.env, expected_env); + assert_eq!(exec_params.network, turn_context.config.network); assert_eq!(exec_params.expiration.timeout_ms(), timeout_ms); assert_eq!(exec_params.sandbox_permissions, sandbox_permissions); assert_eq!(exec_params.justification, justification); diff --git a/codex-rs/core/src/tools/runtimes/apply_patch.rs b/codex-rs/core/src/tools/runtimes/apply_patch.rs index ff22a9cbcf..5ebdd5853a 100644 --- a/codex-rs/core/src/tools/runtimes/apply_patch.rs +++ b/codex-rs/core/src/tools/runtimes/apply_patch.rs @@ -153,7 +153,7 @@ impl ToolRuntime for ApplyPatchRuntime { let env = attempt .env_for(spec) .map_err(|err| ToolError::Codex(err.into()))?; - let out = execute_env(env, attempt.policy, Self::stdout_stream(ctx)) + let out = execute_env(env, attempt.policy, Self::stdout_stream(ctx), None) .await .map_err(ToolError::Codex)?; Ok(out) diff --git a/codex-rs/core/src/tools/runtimes/shell.rs b/codex-rs/core/src/tools/runtimes/shell.rs index fc862a9aea..3afe0840a9 100644 --- a/codex-rs/core/src/tools/runtimes/shell.rs +++ b/codex-rs/core/src/tools/runtimes/shell.rs @@ -23,6 +23,7 @@ use crate::tools::sandboxing::ToolCtx; use crate::tools::sandboxing::ToolError; use crate::tools::sandboxing::ToolRuntime; use crate::tools::sandboxing::with_cached_approval; +use codex_network_proxy::NetworkProxy; use codex_protocol::protocol::ReviewDecision; use futures::future::BoxFuture; use std::path::PathBuf; @@ -33,6 +34,7 @@ pub struct ShellRequest { pub cwd: PathBuf, pub timeout_ms: Option, pub env: std::collections::HashMap, + pub network: Option, pub sandbox_permissions: SandboxPermissions, pub justification: Option, pub exec_approval_requirement: ExecApprovalRequirement, @@ -155,10 +157,11 @@ impl ToolRuntime for ShellRuntime { command }; + let env = req.env.clone(); let spec = build_command_spec( &command, &req.cwd, - &req.env, + &env, req.timeout_ms.into(), req.sandbox_permissions, req.justification.clone(), @@ -166,9 +169,14 @@ impl ToolRuntime for ShellRuntime { let env = attempt .env_for(spec) .map_err(|err| ToolError::Codex(err.into()))?; - let out = execute_env(env, attempt.policy, Self::stdout_stream(ctx)) - .await - .map_err(ToolError::Codex)?; + let out = execute_env( + env, + attempt.policy, + Self::stdout_stream(ctx), + req.network.clone(), + ) + .await + .map_err(ToolError::Codex)?; Ok(out) } } diff --git a/codex-rs/core/src/tools/runtimes/unified_exec.rs b/codex-rs/core/src/tools/runtimes/unified_exec.rs index 2505b10ed2..2c13107fdb 100644 --- a/codex-rs/core/src/tools/runtimes/unified_exec.rs +++ b/codex-rs/core/src/tools/runtimes/unified_exec.rs @@ -27,6 +27,7 @@ use crate::tools::sandboxing::with_cached_approval; use crate::unified_exec::UnifiedExecError; use crate::unified_exec::UnifiedExecProcess; use crate::unified_exec::UnifiedExecProcessManager; +use codex_network_proxy::NetworkProxy; use codex_protocol::protocol::ReviewDecision; use futures::future::BoxFuture; use std::collections::HashMap; @@ -37,6 +38,7 @@ pub struct UnifiedExecRequest { pub command: Vec, pub cwd: PathBuf, pub env: HashMap, + pub network: Option, pub tty: bool, pub sandbox_permissions: SandboxPermissions, pub justification: Option, @@ -55,28 +57,6 @@ pub struct UnifiedExecRuntime<'a> { manager: &'a UnifiedExecProcessManager, } -impl UnifiedExecRequest { - pub fn new( - command: Vec, - cwd: PathBuf, - env: HashMap, - tty: bool, - sandbox_permissions: SandboxPermissions, - justification: Option, - exec_approval_requirement: ExecApprovalRequirement, - ) -> Self { - Self { - command, - cwd, - env, - tty, - sandbox_permissions, - justification, - exec_approval_requirement, - } - } -} - impl<'a> UnifiedExecRuntime<'a> { pub fn new(manager: &'a UnifiedExecProcessManager) -> Self { Self { manager } @@ -181,10 +161,14 @@ impl<'a> ToolRuntime for UnifiedExecRunt command }; + let mut env = req.env.clone(); + if let Some(network) = req.network.as_ref() { + network.apply_to_env(&mut env); + } let spec = build_command_spec( &command, &req.cwd, - &req.env, + &env, ExecExpiration::DefaultTimeout, req.sandbox_permissions, req.justification.clone(), diff --git a/codex-rs/core/src/unified_exec/process_manager.rs b/codex-rs/core/src/unified_exec/process_manager.rs index 1659ba6951..a81b36c7a1 100644 --- a/codex-rs/core/src/unified_exec/process_manager.rs +++ b/codex-rs/core/src/unified_exec/process_manager.rs @@ -501,15 +501,16 @@ impl UnifiedExecProcessManager { prefix_rule: request.prefix_rule.clone(), }) .await; - let req = UnifiedExecToolRequest::new( - request.command.clone(), + let req = UnifiedExecToolRequest { + command: request.command.clone(), cwd, env, - request.tty, - request.sandbox_permissions, - request.justification.clone(), + network: context.turn.config.network.clone(), + tty: request.tty, + sandbox_permissions: request.sandbox_permissions, + justification: request.justification.clone(), exec_approval_requirement, - ); + }; let tool_ctx = ToolCtx { session: context.session.as_ref(), turn: context.turn.as_ref(), diff --git a/codex-rs/core/tests/suite/exec.rs b/codex-rs/core/tests/suite/exec.rs index b70062d7ed..c3cb15875b 100644 --- a/codex-rs/core/tests/suite/exec.rs +++ b/codex-rs/core/tests/suite/exec.rs @@ -36,6 +36,7 @@ async fn run_test_cmd(tmp: TempDir, cmd: Vec<&str>) -> Result>, } +impl std::fmt::Debug for NetworkProxy { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // Avoid logging internal state (config contents, derived globsets, etc.) which can be noisy + // and may contain sensitive paths. + f.debug_struct("NetworkProxy") + .field("http_addr", &self.http_addr) + .field("socks_addr", &self.socks_addr) + .field("admin_addr", &self.admin_addr) + .finish_non_exhaustive() + } +} + +impl PartialEq for NetworkProxy { + fn eq(&self, other: &Self) -> bool { + self.http_addr == other.http_addr + && self.socks_addr == other.socks_addr + && self.admin_addr == other.admin_addr + } +} + +impl Eq for NetworkProxy {} + impl NetworkProxy { pub fn builder() -> NetworkProxyBuilder { NetworkProxyBuilder::default() } + pub fn apply_to_env(&self, env: &mut HashMap) { + // Enforce proxying for all child processes when configured. We always override to ensure + // the proxy is actually used even if the caller passed conflicting environment variables. + let proxy_url = format!("http://{}", self.http_addr); + for key in ["HTTP_PROXY", "HTTPS_PROXY", "http_proxy", "https_proxy"] { + env.insert(key.to_string(), proxy_url.clone()); + } + } + pub async fn run(&self) -> Result { let current_cfg = self.state.current_cfg().await?; if !current_cfg.network.enabled {