mirror of
https://github.com/openai/codex.git
synced 2026-05-29 23:40:29 +00:00
Preserve Linux CA bundles for MITM trust
This commit is contained in:
@@ -300,7 +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,
|
||||
/*mitm_ca_cert_path*/ None,
|
||||
);
|
||||
spawn_debug_sandbox_child(
|
||||
codex_linux_sandbox_exe,
|
||||
|
||||
@@ -34,7 +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 mitm_ca_cert_path = network.and_then(NetworkProxy::mitm_ca_cert_path);
|
||||
let args = create_linux_sandbox_command_args_for_permission_profile(
|
||||
command,
|
||||
command_cwd.as_path(),
|
||||
@@ -42,7 +42,7 @@ where
|
||||
sandbox_policy_cwd,
|
||||
use_legacy_landlock,
|
||||
allow_network_for_proxy(/*enforce_managed_network*/ false),
|
||||
mitm_ca_trust_bundle_path.as_deref(),
|
||||
mitm_ca_cert_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
|
||||
|
||||
@@ -12,12 +12,17 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::HashSet;
|
||||
use std::ffi::CString;
|
||||
use std::ffi::OsString;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::fs::Metadata;
|
||||
use std::io;
|
||||
use std::io::Seek;
|
||||
use std::io::SeekFrom;
|
||||
use std::io::Write;
|
||||
use std::os::fd::AsRawFd;
|
||||
use std::os::fd::FromRawFd;
|
||||
use std::os::unix::ffi::OsStringExt;
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
use std::path::Path;
|
||||
@@ -78,8 +83,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>,
|
||||
/// Managed MITM CA cert to append to common Linux trust-store paths.
|
||||
pub mitm_ca_cert_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Default for BwrapOptions {
|
||||
@@ -88,7 +93,7 @@ impl Default for BwrapOptions {
|
||||
mount_proc: true,
|
||||
network_mode: BwrapNetworkMode::FullAccess,
|
||||
glob_scan_max_depth: None,
|
||||
mitm_ca_trust_bundle_path: None,
|
||||
mitm_ca_cert_path: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -255,7 +260,7 @@ pub(crate) fn create_bwrap_command_args(
|
||||
// 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
|
||||
&& options.mitm_ca_trust_bundle_path.is_none()
|
||||
&& options.mitm_ca_cert_path.is_none()
|
||||
{
|
||||
Ok(BwrapArgs {
|
||||
args: command,
|
||||
@@ -298,10 +303,7 @@ fn create_bwrap_flags_full_filesystem(
|
||||
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(),
|
||||
)?;
|
||||
append_mitm_ca_trust_bundle_args(&mut bwrap_args, options.mitm_ca_cert_path.as_deref())?;
|
||||
if options.network_mode.should_unshare_network() {
|
||||
bwrap_args.args.push("--unshare-net".to_string());
|
||||
}
|
||||
@@ -345,10 +347,7 @@ fn create_bwrap_flags(
|
||||
synthetic_mount_targets,
|
||||
protected_create_targets,
|
||||
};
|
||||
append_mitm_ca_trust_bundle_args(
|
||||
&mut bwrap_args,
|
||||
options.mitm_ca_trust_bundle_path.as_deref(),
|
||||
)?;
|
||||
append_mitm_ca_trust_bundle_args(&mut bwrap_args, options.mitm_ca_cert_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.
|
||||
bwrap_args.args.push("--unshare-user".to_string());
|
||||
@@ -378,31 +377,89 @@ fn create_bwrap_flags(
|
||||
|
||||
fn append_mitm_ca_trust_bundle_args(
|
||||
bwrap_args: &mut BwrapArgs,
|
||||
mitm_ca_trust_bundle_path: Option<&Path>,
|
||||
mitm_ca_cert_path: Option<&Path>,
|
||||
) -> Result<()> {
|
||||
let Some(mitm_ca_trust_bundle_path) = mitm_ca_trust_bundle_path else {
|
||||
let bundle_paths = LINUX_CA_BUNDLE_PATHS.map(Path::new);
|
||||
append_mitm_ca_trust_bundle_args_for_paths(bwrap_args, mitm_ca_cert_path, &bundle_paths)
|
||||
}
|
||||
|
||||
fn append_mitm_ca_trust_bundle_args_for_paths(
|
||||
bwrap_args: &mut BwrapArgs,
|
||||
mitm_ca_cert_path: Option<&Path>,
|
||||
bundle_paths: &[&Path],
|
||||
) -> Result<()> {
|
||||
let Some(mitm_ca_cert_path) = mitm_ca_cert_path else {
|
||||
return Ok(());
|
||||
};
|
||||
let managed_ca_cert = fs::read(mitm_ca_cert_path).map_err(|err| {
|
||||
CodexErr::Fatal(format!(
|
||||
"failed to read managed MITM CA cert {}: {err}",
|
||||
mitm_ca_cert_path.display()
|
||||
))
|
||||
})?;
|
||||
|
||||
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()
|
||||
))
|
||||
})?;
|
||||
for bundle_path in bundle_paths {
|
||||
// Only overlay trust-store files the sandbox would already have seen.
|
||||
let Ok(system_bundle) = fs::read(bundle_path) else {
|
||||
continue;
|
||||
};
|
||||
let bundle_file = preserved_file_from_bytes(build_mitm_ca_bundle_overlay(
|
||||
system_bundle,
|
||||
&managed_ca_cert,
|
||||
))?;
|
||||
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());
|
||||
bwrap_args.args.push(path_to_string(bundle_path));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_mitm_ca_bundle_overlay(mut system_bundle: Vec<u8>, managed_ca_cert: &[u8]) -> Vec<u8> {
|
||||
append_pem_bytes(&mut system_bundle, managed_ca_cert);
|
||||
system_bundle
|
||||
}
|
||||
|
||||
fn append_pem_bytes(bundle: &mut Vec<u8>, pem: &[u8]) {
|
||||
if !bundle.is_empty() && !bundle.ends_with(b"\n") {
|
||||
bundle.push(b'\n');
|
||||
}
|
||||
bundle.extend_from_slice(pem);
|
||||
if !bundle.ends_with(b"\n") {
|
||||
bundle.push(b'\n');
|
||||
}
|
||||
}
|
||||
|
||||
fn preserved_file_from_bytes(contents: Vec<u8>) -> Result<File> {
|
||||
let memfd_name = CString::new("codex-mitm-ca-bundle").expect("static memfd name");
|
||||
// SAFETY: `memfd_name` is a valid NUL-terminated C string and the flags are valid.
|
||||
let fd = unsafe { libc::memfd_create(memfd_name.as_ptr(), libc::MFD_CLOEXEC) };
|
||||
if fd < 0 {
|
||||
return Err(CodexErr::Fatal(format!(
|
||||
"failed to create managed MITM CA bundle memfd: {}",
|
||||
io::Error::last_os_error()
|
||||
)));
|
||||
}
|
||||
|
||||
// SAFETY: `fd` is a newly created owned file descriptor from `memfd_create`.
|
||||
let mut file = unsafe { File::from_raw_fd(fd) };
|
||||
file.write_all(&contents).map_err(|err| {
|
||||
CodexErr::Fatal(format!(
|
||||
"failed to write managed MITM CA bundle memfd: {err}"
|
||||
))
|
||||
})?;
|
||||
file.seek(SeekFrom::Start(0)).map_err(|err| {
|
||||
CodexErr::Fatal(format!(
|
||||
"failed to rewind managed MITM CA bundle memfd: {err}"
|
||||
))
|
||||
})?;
|
||||
Ok(file)
|
||||
}
|
||||
|
||||
/// Build the bubblewrap filesystem mounts for a given filesystem policy.
|
||||
///
|
||||
/// The mount order is important:
|
||||
@@ -1400,8 +1457,8 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_mitm_ca_trust_bundle_path_is_unset() {
|
||||
assert_eq!(BwrapOptions::default().mitm_ca_trust_bundle_path, None);
|
||||
fn default_mitm_ca_cert_path_is_unset() {
|
||||
assert_eq!(BwrapOptions::default().mitm_ca_cert_path, None);
|
||||
}
|
||||
|
||||
fn unreadable_glob_entry(pattern: String) -> FileSystemSandboxEntry {
|
||||
@@ -1472,32 +1529,39 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mitm_ca_trust_bundle_overlays_common_linux_bundle_paths() {
|
||||
fn mitm_ca_cert_appends_to_existing_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 mitm_ca_cert_path = temp_dir.path().join("ca.pem");
|
||||
fs::write(&mitm_ca_cert_path, "managed ca").expect("write managed CA");
|
||||
let system_bundle_path = temp_dir.path().join("ca-certificates.crt");
|
||||
fs::write(&system_bundle_path, "system bundle").expect("write system bundle");
|
||||
let missing_bundle_path = temp_dir.path().join("missing-bundle.crt");
|
||||
let mut args = BwrapArgs {
|
||||
args: Vec::new(),
|
||||
preserved_files: Vec::new(),
|
||||
synthetic_mount_targets: Vec::new(),
|
||||
protected_create_targets: Vec::new(),
|
||||
};
|
||||
|
||||
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()
|
||||
},
|
||||
append_mitm_ca_trust_bundle_args_for_paths(
|
||||
&mut args,
|
||||
Some(&mitm_ca_cert_path),
|
||||
&[&system_bundle_path, &missing_bundle_path],
|
||||
)
|
||||
.expect("create bwrap args");
|
||||
.expect("append MITM CA trust bundle 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
|
||||
}));
|
||||
}
|
||||
assert_eq!(args.preserved_files.len(), 1);
|
||||
let system_bundle_path = path_to_string(&system_bundle_path);
|
||||
assert!(args.args.windows(5).any(|window| {
|
||||
window[0] == "--perms"
|
||||
&& window[1] == "444"
|
||||
&& window[2] == "--ro-bind-data"
|
||||
&& window[4] == system_bundle_path
|
||||
}));
|
||||
let mut overlay_contents = String::new();
|
||||
std::io::Read::read_to_string(&mut args.preserved_files[0], &mut overlay_contents)
|
||||
.expect("read overlay contents");
|
||||
assert_eq!(overlay_contents, "system bundle\nmanaged ca\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -126,9 +126,9 @@ 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>,
|
||||
/// Internal managed MITM CA cert to add to bubblewrap trust bundles.
|
||||
#[arg(long = "mitm-ca-cert", hide = true)]
|
||||
pub mitm_ca_cert_path: Option<PathBuf>,
|
||||
|
||||
/// When set, skip mounting a fresh `/proc` even though PID isolation is
|
||||
/// still enabled. This is primarily intended for restrictive container
|
||||
@@ -157,7 +157,7 @@ pub fn run_main() -> ! {
|
||||
apply_seccomp_then_exec,
|
||||
allow_network_for_proxy,
|
||||
proxy_route_spec,
|
||||
mitm_ca_trust_bundle_path,
|
||||
mitm_ca_cert_path,
|
||||
no_proc,
|
||||
command,
|
||||
} = LandlockCommand::parse();
|
||||
@@ -204,7 +204,7 @@ pub fn run_main() -> ! {
|
||||
|
||||
if file_system_sandbox_policy.has_full_disk_write_access()
|
||||
&& !allow_network_for_proxy
|
||||
&& mitm_ca_trust_bundle_path.is_none()
|
||||
&& mitm_ca_cert_path.is_none()
|
||||
{
|
||||
if let Err(e) = apply_permission_profile_to_current_thread(
|
||||
&permission_profile,
|
||||
@@ -246,7 +246,7 @@ pub fn run_main() -> ! {
|
||||
inner,
|
||||
!no_proc,
|
||||
allow_network_for_proxy,
|
||||
mitm_ca_trust_bundle_path.as_deref(),
|
||||
mitm_ca_cert_path.as_deref(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -331,7 +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>,
|
||||
mitm_ca_cert_path: Option<&Path>,
|
||||
) -> ! {
|
||||
let network_mode = bwrap_network_mode(network_sandbox_policy, allow_network_for_proxy);
|
||||
let mut mount_proc = mount_proc;
|
||||
@@ -343,7 +343,7 @@ fn run_bwrap_with_proc_fallback(
|
||||
command_cwd,
|
||||
file_system_sandbox_policy,
|
||||
network_mode,
|
||||
mitm_ca_trust_bundle_path,
|
||||
mitm_ca_cert_path,
|
||||
)
|
||||
.unwrap_or_else(|err| exit_with_bwrap_build_error(err))
|
||||
{
|
||||
@@ -355,7 +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),
|
||||
mitm_ca_cert_path: mitm_ca_cert_path.map(Path::to_path_buf),
|
||||
..Default::default()
|
||||
};
|
||||
let mut bwrap_args = build_bwrap_argv(
|
||||
@@ -458,14 +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>,
|
||||
mitm_ca_cert_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,
|
||||
mitm_ca_cert_path,
|
||||
)?;
|
||||
let stderr = run_bwrap_in_child_capture_stderr(preflight_argv);
|
||||
Ok(!is_proc_mount_failure(stderr.as_str()))
|
||||
@@ -476,7 +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>,
|
||||
mitm_ca_cert_path: Option<&Path>,
|
||||
) -> CodexResult<crate::bwrap::BwrapArgs> {
|
||||
let preflight_command = vec![resolve_true_command()];
|
||||
build_bwrap_argv(
|
||||
@@ -487,7 +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),
|
||||
mitm_ca_cert_path: mitm_ca_cert_path.map(Path::to_path_buf),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
|
||||
@@ -37,8 +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.
|
||||
# Linux bubblewrap sandboxes also append the managed CA cert to 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.
|
||||
|
||||
@@ -125,6 +125,10 @@ fn managed_ca_paths() -> Result<(PathBuf, PathBuf)> {
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) fn managed_ca_cert_path() -> Result<PathBuf> {
|
||||
managed_ca_paths().map(|(cert_path, _)| cert_path)
|
||||
}
|
||||
|
||||
pub(crate) fn managed_ca_trust_bundle_path(env: &HashMap<String, String>) -> Result<PathBuf> {
|
||||
let (cert_path, _) = managed_ca_paths()?;
|
||||
let trust_bundle_path = cert_path
|
||||
|
||||
@@ -301,20 +301,26 @@ struct NetworkProxyRuntimeSettings {
|
||||
allow_local_binding: bool,
|
||||
allow_unix_sockets: Arc<[String]>,
|
||||
dangerously_allow_all_unix_sockets: bool,
|
||||
mitm_ca_cert_path: Option<PathBuf>,
|
||||
mitm_ca_trust_bundle_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl NetworkProxyRuntimeSettings {
|
||||
fn from_config(config: &config::NetworkProxyConfig) -> Result<Self> {
|
||||
let mitm_ca_trust_bundle_path = config
|
||||
.network
|
||||
.mitm
|
||||
.then(|| crate::certs::managed_ca_trust_bundle_path(&std::env::vars().collect()))
|
||||
.transpose()?;
|
||||
let (mitm_ca_cert_path, mitm_ca_trust_bundle_path) = if config.network.mitm {
|
||||
let env = std::env::vars().collect();
|
||||
(
|
||||
Some(crate::certs::managed_ca_cert_path()?),
|
||||
Some(crate::certs::managed_ca_trust_bundle_path(&env)?),
|
||||
)
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
Ok(Self {
|
||||
allow_local_binding: config.network.allow_local_binding,
|
||||
allow_unix_sockets: config.network.allow_unix_sockets().into(),
|
||||
dangerously_allow_all_unix_sockets: config.network.dangerously_allow_all_unix_sockets,
|
||||
mitm_ca_cert_path,
|
||||
mitm_ca_trust_bundle_path,
|
||||
})
|
||||
}
|
||||
@@ -614,9 +620,9 @@ 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
|
||||
/// Returns the managed CA cert child sandboxes should add to native trust paths.
|
||||
pub fn mitm_ca_cert_path(&self) -> Option<PathBuf> {
|
||||
self.runtime_settings().mitm_ca_cert_path
|
||||
}
|
||||
|
||||
pub fn apply_to_env(&self, env: &mut HashMap<String, String>) {
|
||||
|
||||
@@ -27,7 +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>,
|
||||
mitm_ca_cert_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}"));
|
||||
@@ -54,12 +54,12 @@ 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());
|
||||
if let Some(mitm_ca_cert_path) = mitm_ca_cert_path {
|
||||
linux_cmd.push("--mitm-ca-cert".to_string());
|
||||
linux_cmd.push(
|
||||
mitm_ca_trust_bundle_path
|
||||
mitm_ca_cert_path
|
||||
.to_str()
|
||||
.unwrap_or_else(|| panic!("MITM CA trust bundle path must be valid UTF-8"))
|
||||
.unwrap_or_else(|| panic!("MITM CA cert path must be valid UTF-8"))
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
@@ -77,7 +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>,
|
||||
mitm_ca_cert_path: Option<&Path>,
|
||||
) -> Vec<String> {
|
||||
let command_cwd = command_cwd
|
||||
.to_str()
|
||||
@@ -100,12 +100,12 @@ 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());
|
||||
if let Some(mitm_ca_cert_path) = mitm_ca_cert_path {
|
||||
linux_cmd.push("--mitm-ca-cert".to_string());
|
||||
linux_cmd.push(
|
||||
mitm_ca_trust_bundle_path
|
||||
mitm_ca_cert_path
|
||||
.to_str()
|
||||
.unwrap_or_else(|| panic!("MITM CA trust bundle path must be valid UTF-8"))
|
||||
.unwrap_or_else(|| panic!("MITM CA cert path must be valid UTF-8"))
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,7 +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,
|
||||
/*mitm_ca_cert_path*/ None,
|
||||
);
|
||||
assert_eq!(
|
||||
default_bwrap.contains(&"--use-legacy-landlock".to_string()),
|
||||
@@ -26,7 +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,
|
||||
/*mitm_ca_cert_path*/ None,
|
||||
);
|
||||
assert_eq!(
|
||||
legacy_landlock.contains(&"--use-legacy-landlock".to_string()),
|
||||
@@ -46,7 +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,
|
||||
/*mitm_ca_cert_path*/ None,
|
||||
);
|
||||
assert_eq!(
|
||||
args.contains(&"--allow-network-for-proxy".to_string()),
|
||||
@@ -68,7 +68,7 @@ fn permission_profile_flag_is_included() {
|
||||
cwd,
|
||||
/*use_legacy_landlock*/ true,
|
||||
/*allow_network_for_proxy*/ false,
|
||||
/*mitm_ca_trust_bundle_path*/ None,
|
||||
/*mitm_ca_cert_path*/ None,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
@@ -84,11 +84,11 @@ fn permission_profile_flag_is_included() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mitm_ca_trust_bundle_flag_is_included_when_requested() {
|
||||
fn mitm_ca_cert_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 cert_path = Path::new("/tmp/ca.pem");
|
||||
|
||||
let args = create_linux_sandbox_command_args(
|
||||
command,
|
||||
@@ -96,12 +96,13 @@ fn mitm_ca_trust_bundle_flag_is_included_when_requested() {
|
||||
cwd,
|
||||
/*use_legacy_landlock*/ false,
|
||||
/*allow_network_for_proxy*/ true,
|
||||
Some(trust_bundle_path),
|
||||
Some(cert_path),
|
||||
);
|
||||
|
||||
assert!(args.windows(2).any(|window| {
|
||||
window[0] == "--mitm-ca-trust-bundle" && window[1] == "/tmp/ca-bundle.pem"
|
||||
}));
|
||||
assert!(
|
||||
args.windows(2)
|
||||
.any(|window| { window[0] == "--mitm-ca-cert" && window[1] == "/tmp/ca.pem" })
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -218,8 +218,7 @@ 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);
|
||||
let mitm_ca_cert_path = network.and_then(NetworkProxy::mitm_ca_cert_path);
|
||||
#[cfg(target_os = "linux")]
|
||||
ensure_linux_bubblewrap_is_supported(
|
||||
&effective_file_system_policy,
|
||||
@@ -234,7 +233,7 @@ impl SandboxManager {
|
||||
sandbox_policy_cwd,
|
||||
use_legacy_landlock,
|
||||
allow_proxy_network,
|
||||
mitm_ca_trust_bundle_path.as_deref(),
|
||||
mitm_ca_cert_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