mirror of
https://github.com/openai/codex.git
synced 2026-05-29 23:40:29 +00:00
Trust managed MITM CA in Linux sandboxes
This commit is contained in:
@@ -300,6 +300,7 @@ async fn run_command_under_sandbox(
|
||||
sandbox_policy_cwd.as_path(),
|
||||
use_legacy_landlock,
|
||||
allow_network_for_proxy(managed_network_requirements_enabled),
|
||||
/*mitm_ca_trust_bundle_path*/ None,
|
||||
);
|
||||
spawn_debug_sandbox_child(
|
||||
codex_linux_sandbox_exe,
|
||||
|
||||
@@ -34,6 +34,7 @@ where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let network_sandbox_policy = permission_profile.network_sandbox_policy();
|
||||
let mitm_ca_trust_bundle_path = network.and_then(NetworkProxy::mitm_ca_trust_bundle_path);
|
||||
let args = create_linux_sandbox_command_args_for_permission_profile(
|
||||
command,
|
||||
command_cwd.as_path(),
|
||||
@@ -41,6 +42,7 @@ where
|
||||
sandbox_policy_cwd,
|
||||
use_legacy_landlock,
|
||||
allow_network_for_proxy(/*enforce_managed_network*/ false),
|
||||
mitm_ca_trust_bundle_path.as_deref(),
|
||||
);
|
||||
let codex_linux_sandbox_exe = codex_linux_sandbox_exe.as_ref();
|
||||
// Preserve the helper alias when we already have it; otherwise force argv0
|
||||
|
||||
@@ -54,9 +54,17 @@ const LINUX_PLATFORM_DEFAULT_READ_ROOTS: &[&str] = &[
|
||||
];
|
||||
|
||||
const MAX_UNREADABLE_GLOB_MATCHES: usize = 8192;
|
||||
// Common Linux trust bundle paths for clients that read system roots instead of
|
||||
// honoring one of the CA bundle environment variables we export.
|
||||
const LINUX_CA_BUNDLE_PATHS: [&str; 4] = [
|
||||
"/etc/ssl/certs/ca-certificates.crt",
|
||||
"/etc/pki/tls/certs/ca-bundle.crt",
|
||||
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem",
|
||||
"/etc/ssl/cert.pem",
|
||||
];
|
||||
|
||||
/// Options that control how bubblewrap is invoked.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(crate) struct BwrapOptions {
|
||||
/// Whether to mount a fresh `/proc` inside the sandbox.
|
||||
///
|
||||
@@ -70,6 +78,8 @@ pub(crate) struct BwrapOptions {
|
||||
/// Keep this uncapped by default so existing nested deny-read matches are
|
||||
/// masked before the sandboxed command starts.
|
||||
pub glob_scan_max_depth: Option<usize>,
|
||||
/// Managed MITM CA bundle to materialize at common Linux trust-store paths.
|
||||
pub mitm_ca_trust_bundle_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Default for BwrapOptions {
|
||||
@@ -78,6 +88,7 @@ impl Default for BwrapOptions {
|
||||
mount_proc: true,
|
||||
network_mode: BwrapNetworkMode::FullAccess,
|
||||
glob_scan_max_depth: None,
|
||||
mitm_ca_trust_bundle_path: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,7 +254,9 @@ pub(crate) fn create_bwrap_command_args(
|
||||
// Full disk write normally skips bwrap, but unreadable glob patterns still
|
||||
// need concrete bwrap masks for the matches expanded below.
|
||||
if file_system_sandbox_policy.has_full_disk_write_access() && unreadable_globs.is_empty() {
|
||||
return if options.network_mode == BwrapNetworkMode::FullAccess {
|
||||
return if options.network_mode == BwrapNetworkMode::FullAccess
|
||||
&& options.mitm_ca_trust_bundle_path.is_none()
|
||||
{
|
||||
Ok(BwrapArgs {
|
||||
args: command,
|
||||
preserved_files: Vec::new(),
|
||||
@@ -251,7 +264,7 @@ pub(crate) fn create_bwrap_command_args(
|
||||
protected_create_targets: Vec::new(),
|
||||
})
|
||||
} else {
|
||||
Ok(create_bwrap_flags_full_filesystem(command, options))
|
||||
create_bwrap_flags_full_filesystem(command, options)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -264,8 +277,11 @@ pub(crate) fn create_bwrap_command_args(
|
||||
)
|
||||
}
|
||||
|
||||
fn create_bwrap_flags_full_filesystem(command: Vec<String>, options: BwrapOptions) -> BwrapArgs {
|
||||
let mut args = vec![
|
||||
fn create_bwrap_flags_full_filesystem(
|
||||
command: Vec<String>,
|
||||
options: BwrapOptions,
|
||||
) -> Result<BwrapArgs> {
|
||||
let args = vec![
|
||||
"--new-session".to_string(),
|
||||
"--die-with-parent".to_string(),
|
||||
"--bind".to_string(),
|
||||
@@ -276,21 +292,26 @@ fn create_bwrap_flags_full_filesystem(command: Vec<String>, options: BwrapOption
|
||||
"--unshare-user".to_string(),
|
||||
"--unshare-pid".to_string(),
|
||||
];
|
||||
if options.network_mode.should_unshare_network() {
|
||||
args.push("--unshare-net".to_string());
|
||||
}
|
||||
if options.mount_proc {
|
||||
args.push("--proc".to_string());
|
||||
args.push("/proc".to_string());
|
||||
}
|
||||
args.push("--".to_string());
|
||||
args.extend(command);
|
||||
BwrapArgs {
|
||||
let mut bwrap_args = BwrapArgs {
|
||||
args,
|
||||
preserved_files: Vec::new(),
|
||||
synthetic_mount_targets: Vec::new(),
|
||||
protected_create_targets: Vec::new(),
|
||||
};
|
||||
append_mitm_ca_trust_bundle_args(
|
||||
&mut bwrap_args,
|
||||
options.mitm_ca_trust_bundle_path.as_deref(),
|
||||
)?;
|
||||
if options.network_mode.should_unshare_network() {
|
||||
bwrap_args.args.push("--unshare-net".to_string());
|
||||
}
|
||||
if options.mount_proc {
|
||||
bwrap_args.args.push("--proc".to_string());
|
||||
bwrap_args.args.push("/proc".to_string());
|
||||
}
|
||||
bwrap_args.args.push("--".to_string());
|
||||
bwrap_args.args.extend(command);
|
||||
Ok(bwrap_args)
|
||||
}
|
||||
|
||||
/// Build the bubblewrap flags (everything after `argv[0]`).
|
||||
@@ -318,34 +339,68 @@ fn create_bwrap_flags(
|
||||
args.push("--new-session".to_string());
|
||||
args.push("--die-with-parent".to_string());
|
||||
args.extend(filesystem_args);
|
||||
let mut bwrap_args = BwrapArgs {
|
||||
args,
|
||||
preserved_files,
|
||||
synthetic_mount_targets,
|
||||
protected_create_targets,
|
||||
};
|
||||
append_mitm_ca_trust_bundle_args(
|
||||
&mut bwrap_args,
|
||||
options.mitm_ca_trust_bundle_path.as_deref(),
|
||||
)?;
|
||||
// Request a user namespace explicitly rather than relying on bubblewrap's
|
||||
// auto-enable behavior, which is skipped when the caller runs as uid 0.
|
||||
args.push("--unshare-user".to_string());
|
||||
args.push("--unshare-pid".to_string());
|
||||
bwrap_args.args.push("--unshare-user".to_string());
|
||||
bwrap_args.args.push("--unshare-pid".to_string());
|
||||
if options.network_mode.should_unshare_network() {
|
||||
args.push("--unshare-net".to_string());
|
||||
bwrap_args.args.push("--unshare-net".to_string());
|
||||
}
|
||||
// Mount a fresh /proc unless the caller explicitly disables it.
|
||||
if options.mount_proc {
|
||||
args.push("--proc".to_string());
|
||||
args.push("/proc".to_string());
|
||||
bwrap_args.args.push("--proc".to_string());
|
||||
bwrap_args.args.push("/proc".to_string());
|
||||
}
|
||||
if normalized_command_cwd.as_path() != command_cwd {
|
||||
// Bubblewrap otherwise inherits the helper's logical cwd, which can be
|
||||
// a symlink alias that disappears once the sandbox only mounts
|
||||
// canonical roots. Enter the canonical command cwd explicitly so
|
||||
// relative paths stay aligned with the mounted filesystem view.
|
||||
args.push("--chdir".to_string());
|
||||
args.push(path_to_string(normalized_command_cwd.as_path()));
|
||||
bwrap_args.args.push("--chdir".to_string());
|
||||
bwrap_args
|
||||
.args
|
||||
.push(path_to_string(normalized_command_cwd.as_path()));
|
||||
}
|
||||
args.push("--".to_string());
|
||||
args.extend(command);
|
||||
Ok(BwrapArgs {
|
||||
args,
|
||||
preserved_files,
|
||||
synthetic_mount_targets,
|
||||
protected_create_targets,
|
||||
})
|
||||
bwrap_args.args.push("--".to_string());
|
||||
bwrap_args.args.extend(command);
|
||||
Ok(bwrap_args)
|
||||
}
|
||||
|
||||
fn append_mitm_ca_trust_bundle_args(
|
||||
bwrap_args: &mut BwrapArgs,
|
||||
mitm_ca_trust_bundle_path: Option<&Path>,
|
||||
) -> Result<()> {
|
||||
let Some(mitm_ca_trust_bundle_path) = mitm_ca_trust_bundle_path else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
for bundle_path in LINUX_CA_BUNDLE_PATHS {
|
||||
let bundle_file = File::open(mitm_ca_trust_bundle_path).map_err(|err| {
|
||||
CodexErr::Fatal(format!(
|
||||
"failed to open managed MITM CA trust bundle {}: {err}",
|
||||
mitm_ca_trust_bundle_path.display()
|
||||
))
|
||||
})?;
|
||||
let bundle_fd = bundle_file.as_raw_fd().to_string();
|
||||
bwrap_args.preserved_files.push(bundle_file);
|
||||
bwrap_args.args.push("--perms".to_string());
|
||||
bwrap_args.args.push("444".to_string());
|
||||
bwrap_args.args.push("--ro-bind-data".to_string());
|
||||
bwrap_args.args.push(bundle_fd);
|
||||
bwrap_args.args.push(bundle_path.to_string());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Build the bubblewrap filesystem mounts for a given filesystem policy.
|
||||
@@ -1344,6 +1399,11 @@ mod tests {
|
||||
assert_eq!(BwrapOptions::default().glob_scan_max_depth, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_mitm_ca_trust_bundle_path_is_unset() {
|
||||
assert_eq!(BwrapOptions::default().mitm_ca_trust_bundle_path, None);
|
||||
}
|
||||
|
||||
fn unreadable_glob_entry(pattern: String) -> FileSystemSandboxEntry {
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::GlobPattern { pattern },
|
||||
@@ -1411,6 +1471,35 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mitm_ca_trust_bundle_overlays_common_linux_bundle_paths() {
|
||||
let temp_dir = TempDir::new().expect("tempdir");
|
||||
let mitm_ca_trust_bundle_path = temp_dir.path().join("ca-bundle.pem");
|
||||
fs::write(&mitm_ca_trust_bundle_path, "managed bundle").expect("write bundle");
|
||||
|
||||
let args = create_bwrap_command_args(
|
||||
vec!["/bin/true".to_string()],
|
||||
&FileSystemSandboxPolicy::unrestricted(),
|
||||
Path::new("/"),
|
||||
Path::new("/"),
|
||||
BwrapOptions {
|
||||
mitm_ca_trust_bundle_path: Some(mitm_ca_trust_bundle_path),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.expect("create bwrap args");
|
||||
|
||||
assert_eq!(args.preserved_files.len(), LINUX_CA_BUNDLE_PATHS.len());
|
||||
for bundle_path in LINUX_CA_BUNDLE_PATHS {
|
||||
assert!(args.args.windows(5).any(|window| {
|
||||
window[0] == "--perms"
|
||||
&& window[1] == "444"
|
||||
&& window[2] == "--ro-bind-data"
|
||||
&& window[4] == bundle_path
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn full_disk_write_with_unreadable_glob_still_wraps_and_masks_match() {
|
||||
if !ripgrep_available() {
|
||||
|
||||
@@ -126,6 +126,10 @@ pub struct LandlockCommand {
|
||||
#[arg(long = "proxy-route-spec", hide = true)]
|
||||
pub proxy_route_spec: Option<String>,
|
||||
|
||||
/// Internal managed MITM CA bundle to materialize in bubblewrap sandboxes.
|
||||
#[arg(long = "mitm-ca-trust-bundle", hide = true)]
|
||||
pub mitm_ca_trust_bundle_path: Option<PathBuf>,
|
||||
|
||||
/// When set, skip mounting a fresh `/proc` even though PID isolation is
|
||||
/// still enabled. This is primarily intended for restrictive container
|
||||
/// environments that deny `--proc /proc`.
|
||||
@@ -153,6 +157,7 @@ pub fn run_main() -> ! {
|
||||
apply_seccomp_then_exec,
|
||||
allow_network_for_proxy,
|
||||
proxy_route_spec,
|
||||
mitm_ca_trust_bundle_path,
|
||||
no_proc,
|
||||
command,
|
||||
} = LandlockCommand::parse();
|
||||
@@ -197,7 +202,10 @@ pub fn run_main() -> ! {
|
||||
exec_or_panic(command);
|
||||
}
|
||||
|
||||
if file_system_sandbox_policy.has_full_disk_write_access() && !allow_network_for_proxy {
|
||||
if file_system_sandbox_policy.has_full_disk_write_access()
|
||||
&& !allow_network_for_proxy
|
||||
&& mitm_ca_trust_bundle_path.is_none()
|
||||
{
|
||||
if let Err(e) = apply_permission_profile_to_current_thread(
|
||||
&permission_profile,
|
||||
&sandbox_policy_cwd,
|
||||
@@ -238,6 +246,7 @@ pub fn run_main() -> ! {
|
||||
inner,
|
||||
!no_proc,
|
||||
allow_network_for_proxy,
|
||||
mitm_ca_trust_bundle_path.as_deref(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -322,6 +331,7 @@ fn run_bwrap_with_proc_fallback(
|
||||
inner: Vec<String>,
|
||||
mount_proc: bool,
|
||||
allow_network_for_proxy: bool,
|
||||
mitm_ca_trust_bundle_path: Option<&Path>,
|
||||
) -> ! {
|
||||
let network_mode = bwrap_network_mode(network_sandbox_policy, allow_network_for_proxy);
|
||||
let mut mount_proc = mount_proc;
|
||||
@@ -333,6 +343,7 @@ fn run_bwrap_with_proc_fallback(
|
||||
command_cwd,
|
||||
file_system_sandbox_policy,
|
||||
network_mode,
|
||||
mitm_ca_trust_bundle_path,
|
||||
)
|
||||
.unwrap_or_else(|err| exit_with_bwrap_build_error(err))
|
||||
{
|
||||
@@ -344,6 +355,7 @@ fn run_bwrap_with_proc_fallback(
|
||||
let options = BwrapOptions {
|
||||
mount_proc,
|
||||
network_mode,
|
||||
mitm_ca_trust_bundle_path: mitm_ca_trust_bundle_path.map(Path::to_path_buf),
|
||||
..Default::default()
|
||||
};
|
||||
let mut bwrap_args = build_bwrap_argv(
|
||||
@@ -446,12 +458,14 @@ fn preflight_proc_mount_support(
|
||||
command_cwd: &Path,
|
||||
file_system_sandbox_policy: &FileSystemSandboxPolicy,
|
||||
network_mode: BwrapNetworkMode,
|
||||
mitm_ca_trust_bundle_path: Option<&Path>,
|
||||
) -> CodexResult<bool> {
|
||||
let preflight_argv = build_preflight_bwrap_argv(
|
||||
sandbox_policy_cwd,
|
||||
command_cwd,
|
||||
file_system_sandbox_policy,
|
||||
network_mode,
|
||||
mitm_ca_trust_bundle_path,
|
||||
)?;
|
||||
let stderr = run_bwrap_in_child_capture_stderr(preflight_argv);
|
||||
Ok(!is_proc_mount_failure(stderr.as_str()))
|
||||
@@ -462,6 +476,7 @@ fn build_preflight_bwrap_argv(
|
||||
command_cwd: &Path,
|
||||
file_system_sandbox_policy: &FileSystemSandboxPolicy,
|
||||
network_mode: BwrapNetworkMode,
|
||||
mitm_ca_trust_bundle_path: Option<&Path>,
|
||||
) -> CodexResult<crate::bwrap::BwrapArgs> {
|
||||
let preflight_command = vec![resolve_true_command()];
|
||||
build_bwrap_argv(
|
||||
@@ -472,6 +487,7 @@ fn build_preflight_bwrap_argv(
|
||||
BwrapOptions {
|
||||
mount_proc: true,
|
||||
network_mode,
|
||||
mitm_ca_trust_bundle_path: mitm_ca_trust_bundle_path.map(Path::to_path_buf),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
|
||||
@@ -37,6 +37,8 @@ mode = "full" # default when unset; use "limited" for read-only mode
|
||||
# CA cert/key are managed internally under $CODEX_HOME/proxy/ (ca.pem + ca.key).
|
||||
# When MITM is active, spawned commands receive CA bundle env vars pointing at
|
||||
# $CODEX_HOME/proxy/ca-bundle.pem so common HTTPS clients trust the managed CA.
|
||||
# Linux bubblewrap sandboxes also overlay that bundle onto common system CA
|
||||
# bundle paths inside the sandbox namespace.
|
||||
|
||||
# If false, local/private networking is rejected. Explicit allowlisting of local IP literals
|
||||
# (or `localhost`) is required to permit them.
|
||||
|
||||
@@ -614,6 +614,11 @@ impl NetworkProxy {
|
||||
self.runtime_settings().dangerously_allow_all_unix_sockets
|
||||
}
|
||||
|
||||
/// Returns the managed CA bundle child sandboxes should trust while MITM is active.
|
||||
pub fn mitm_ca_trust_bundle_path(&self) -> Option<PathBuf> {
|
||||
self.runtime_settings().mitm_ca_trust_bundle_path
|
||||
}
|
||||
|
||||
pub fn apply_to_env(&self, env: &mut HashMap<String, String>) {
|
||||
let runtime_settings = self.runtime_settings();
|
||||
// Enforce proxying for child processes. We intentionally override existing values so
|
||||
|
||||
@@ -27,6 +27,7 @@ pub fn create_linux_sandbox_command_args_for_permission_profile(
|
||||
sandbox_policy_cwd: &Path,
|
||||
use_legacy_landlock: bool,
|
||||
allow_network_for_proxy: bool,
|
||||
mitm_ca_trust_bundle_path: Option<&Path>,
|
||||
) -> Vec<String> {
|
||||
let permission_profile_json = serde_json::to_string(permission_profile)
|
||||
.unwrap_or_else(|err| panic!("failed to serialize permission profile: {err}"));
|
||||
@@ -53,6 +54,15 @@ pub fn create_linux_sandbox_command_args_for_permission_profile(
|
||||
if allow_network_for_proxy {
|
||||
linux_cmd.push("--allow-network-for-proxy".to_string());
|
||||
}
|
||||
if let Some(mitm_ca_trust_bundle_path) = mitm_ca_trust_bundle_path {
|
||||
linux_cmd.push("--mitm-ca-trust-bundle".to_string());
|
||||
linux_cmd.push(
|
||||
mitm_ca_trust_bundle_path
|
||||
.to_str()
|
||||
.unwrap_or_else(|| panic!("MITM CA trust bundle path must be valid UTF-8"))
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
linux_cmd.push("--".to_string());
|
||||
linux_cmd.extend(command);
|
||||
linux_cmd
|
||||
@@ -67,6 +77,7 @@ fn create_linux_sandbox_command_args(
|
||||
sandbox_policy_cwd: &Path,
|
||||
use_legacy_landlock: bool,
|
||||
allow_network_for_proxy: bool,
|
||||
mitm_ca_trust_bundle_path: Option<&Path>,
|
||||
) -> Vec<String> {
|
||||
let command_cwd = command_cwd
|
||||
.to_str()
|
||||
@@ -89,6 +100,15 @@ fn create_linux_sandbox_command_args(
|
||||
if allow_network_for_proxy {
|
||||
linux_cmd.push("--allow-network-for-proxy".to_string());
|
||||
}
|
||||
if let Some(mitm_ca_trust_bundle_path) = mitm_ca_trust_bundle_path {
|
||||
linux_cmd.push("--mitm-ca-trust-bundle".to_string());
|
||||
linux_cmd.push(
|
||||
mitm_ca_trust_bundle_path
|
||||
.to_str()
|
||||
.unwrap_or_else(|| panic!("MITM CA trust bundle path must be valid UTF-8"))
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
// Separator so that command arguments starting with `-` are not parsed as
|
||||
// options of the helper itself.
|
||||
|
||||
@@ -13,6 +13,7 @@ fn legacy_landlock_flag_is_included_when_requested() {
|
||||
cwd,
|
||||
/*use_legacy_landlock*/ false,
|
||||
/*allow_network_for_proxy*/ false,
|
||||
/*mitm_ca_trust_bundle_path*/ None,
|
||||
);
|
||||
assert_eq!(
|
||||
default_bwrap.contains(&"--use-legacy-landlock".to_string()),
|
||||
@@ -25,6 +26,7 @@ fn legacy_landlock_flag_is_included_when_requested() {
|
||||
cwd,
|
||||
/*use_legacy_landlock*/ true,
|
||||
/*allow_network_for_proxy*/ false,
|
||||
/*mitm_ca_trust_bundle_path*/ None,
|
||||
);
|
||||
assert_eq!(
|
||||
legacy_landlock.contains(&"--use-legacy-landlock".to_string()),
|
||||
@@ -44,6 +46,7 @@ fn proxy_flag_is_included_when_requested() {
|
||||
cwd,
|
||||
/*use_legacy_landlock*/ true,
|
||||
/*allow_network_for_proxy*/ true,
|
||||
/*mitm_ca_trust_bundle_path*/ None,
|
||||
);
|
||||
assert_eq!(
|
||||
args.contains(&"--allow-network-for-proxy".to_string()),
|
||||
@@ -65,6 +68,7 @@ fn permission_profile_flag_is_included() {
|
||||
cwd,
|
||||
/*use_legacy_landlock*/ true,
|
||||
/*allow_network_for_proxy*/ false,
|
||||
/*mitm_ca_trust_bundle_path*/ None,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
@@ -79,6 +83,27 @@ fn permission_profile_flag_is_included() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mitm_ca_trust_bundle_flag_is_included_when_requested() {
|
||||
let command = vec!["/bin/true".to_string()];
|
||||
let command_cwd = Path::new("/tmp/link");
|
||||
let cwd = Path::new("/tmp");
|
||||
let trust_bundle_path = Path::new("/tmp/ca-bundle.pem");
|
||||
|
||||
let args = create_linux_sandbox_command_args(
|
||||
command,
|
||||
command_cwd,
|
||||
cwd,
|
||||
/*use_legacy_landlock*/ false,
|
||||
/*allow_network_for_proxy*/ true,
|
||||
Some(trust_bundle_path),
|
||||
);
|
||||
|
||||
assert!(args.windows(2).any(|window| {
|
||||
window[0] == "--mitm-ca-trust-bundle" && window[1] == "/tmp/ca-bundle.pem"
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn proxy_network_requires_managed_requirements() {
|
||||
assert_eq!(
|
||||
|
||||
@@ -218,6 +218,8 @@ impl SandboxManager {
|
||||
let exe = codex_linux_sandbox_exe
|
||||
.ok_or(SandboxTransformError::MissingLinuxSandboxExecutable)?;
|
||||
let allow_proxy_network = allow_network_for_proxy(enforce_managed_network);
|
||||
let mitm_ca_trust_bundle_path =
|
||||
network.and_then(NetworkProxy::mitm_ca_trust_bundle_path);
|
||||
#[cfg(target_os = "linux")]
|
||||
ensure_linux_bubblewrap_is_supported(
|
||||
&effective_file_system_policy,
|
||||
@@ -232,6 +234,7 @@ impl SandboxManager {
|
||||
sandbox_policy_cwd,
|
||||
use_legacy_landlock,
|
||||
allow_proxy_network,
|
||||
mitm_ca_trust_bundle_path.as_deref(),
|
||||
);
|
||||
let mut full_command = Vec::with_capacity(1 + args.len());
|
||||
full_command.push(os_string_to_command_component(exe.as_os_str().to_owned()));
|
||||
|
||||
Reference in New Issue
Block a user