mirror of
https://github.com/openai/codex.git
synced 2026-11-09 16:41:37 +00:00
feat(sandbox): enforce proxy-aware network routing in sandbox (#11113)
## Summary - expand proxy env injection to cover common tool env vars (`HTTP_PROXY`/`HTTPS_PROXY`/`ALL_PROXY`/`NO_PROXY` families + tool-specific variants) - harden macOS Seatbelt network policy generation to route through inferred loopback proxy endpoints and fail closed when proxy env is malformed - thread proxy-aware Linux sandbox flags and add minimal bwrap netns isolation hook for restricted non-proxy runs - add/refresh tests for proxy env wiring, Seatbelt policy generation, and Linux sandbox argument wiring
This commit is contained in:
1 parent
b61ea47e83
commit
3391e5ea86
24 files changed
+1046
-122
No files matched your search
@@ -1,6 +1,8 @@
|
||||
use crate::protocol::SandboxPolicy;
|
||||
use crate::spawn::SpawnChildRequest;
|
||||
use crate::spawn::StdioPolicy;
|
||||
use crate::spawn::spawn_child_async;
|
||||
use codex_network_proxy::NetworkProxy;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
@@ -23,6 +25,7 @@ pub async fn spawn_command_under_linux_sandbox<P>(
|
||||
sandbox_policy_cwd: &Path,
|
||||
use_bwrap_sandbox: bool,
|
||||
stdio_policy: StdioPolicy,
|
||||
network: Option<&NetworkProxy>,
|
||||
env: HashMap<String, String>,
|
||||
) -> std::io::Result<Child>
|
||||
where
|
||||
@@ -33,20 +36,29 @@ where
|
||||
sandbox_policy,
|
||||
sandbox_policy_cwd,
|
||||
use_bwrap_sandbox,
|
||||
allow_network_for_proxy(false),
|
||||
);
|
||||
let arg0 = Some("codex-linux-sandbox");
|
||||
spawn_child_async(
|
||||
codex_linux_sandbox_exe.as_ref().to_path_buf(),
|
||||
spawn_child_async(SpawnChildRequest {
|
||||
program: codex_linux_sandbox_exe.as_ref().to_path_buf(),
|
||||
args,
|
||||
arg0,
|
||||
command_cwd,
|
||||
cwd: command_cwd,
|
||||
sandbox_policy,
|
||||
network,
|
||||
stdio_policy,
|
||||
env,
|
||||
)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub(crate) fn allow_network_for_proxy(enforce_managed_network: bool) -> bool {
|
||||
// When managed network requirements are active, request proxy-only
|
||||
// networking from the Linux sandbox helper. Without managed requirements,
|
||||
// preserve existing behavior.
|
||||
enforce_managed_network
|
||||
}
|
||||
|
||||
/// Converts the sandbox policy into the CLI invocation for `codex-linux-sandbox`.
|
||||
///
|
||||
/// The helper performs the actual sandboxing (bubblewrap + seccomp) after
|
||||
@@ -56,6 +68,7 @@ pub(crate) fn create_linux_sandbox_command_args(
|
||||
sandbox_policy: &SandboxPolicy,
|
||||
sandbox_policy_cwd: &Path,
|
||||
use_bwrap_sandbox: bool,
|
||||
allow_network_for_proxy: bool,
|
||||
) -> Vec<String> {
|
||||
#[expect(clippy::expect_used)]
|
||||
let sandbox_policy_cwd = sandbox_policy_cwd
|
||||
@@ -76,6 +89,9 @@ pub(crate) fn create_linux_sandbox_command_args(
|
||||
if use_bwrap_sandbox {
|
||||
linux_cmd.push("--use-bwrap-sandbox".to_string());
|
||||
}
|
||||
if allow_network_for_proxy {
|
||||
linux_cmd.push("--allow-network-for-proxy".to_string());
|
||||
}
|
||||
|
||||
// Separator so that command arguments starting with `-` are not parsed as
|
||||
// options of the helper itself.
|
||||
@@ -98,16 +114,36 @@ mod tests {
|
||||
let cwd = Path::new("/tmp");
|
||||
let policy = SandboxPolicy::ReadOnly;
|
||||
|
||||
let with_bwrap = create_linux_sandbox_command_args(command.clone(), &policy, cwd, true);
|
||||
let with_bwrap =
|
||||
create_linux_sandbox_command_args(command.clone(), &policy, cwd, true, false);
|
||||
assert_eq!(
|
||||
with_bwrap.contains(&"--use-bwrap-sandbox".to_string()),
|
||||
true
|
||||
);
|
||||
|
||||
let without_bwrap = create_linux_sandbox_command_args(command, &policy, cwd, false);
|
||||
let without_bwrap = create_linux_sandbox_command_args(command, &policy, cwd, false, false);
|
||||
assert_eq!(
|
||||
without_bwrap.contains(&"--use-bwrap-sandbox".to_string()),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn proxy_flag_is_included_when_requested() {
|
||||
let command = vec!["/bin/true".to_string()];
|
||||
let cwd = Path::new("/tmp");
|
||||
let policy = SandboxPolicy::ReadOnly;
|
||||
|
||||
let args = create_linux_sandbox_command_args(command, &policy, cwd, true, true);
|
||||
assert_eq!(
|
||||
args.contains(&"--allow-network-for-proxy".to_string()),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn proxy_network_requires_managed_requirements() {
|
||||
assert_eq!(allow_network_for_proxy(false), false);
|
||||
assert_eq!(allow_network_for_proxy(true), true);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user