mirror of
https://github.com/openai/codex.git
synced 2026-09-05 15:18:41 +00:00
fix(sandboxing): scope detached children to shell tools
Co-authored-by: Codex noreply@openai.com
This commit is contained in:
@@ -320,6 +320,7 @@ impl CommandExecRequestProcessor {
|
||||
&sandbox_cwd,
|
||||
&codex_linux_sandbox_exe,
|
||||
use_legacy_landlock,
|
||||
codex_core::exec::SandboxProcessLifetime::TerminateWithParent,
|
||||
)
|
||||
.map_err(|err| internal_error(format!("exec failed: {err}")))?;
|
||||
self.command_exec_manager
|
||||
|
||||
@@ -17,6 +17,7 @@ use codex_core::spawn::CODEX_SANDBOX_ENV_VAR;
|
||||
use codex_core::spawn::CODEX_SANDBOX_NETWORK_DISABLED_ENV_VAR;
|
||||
use codex_protocol::config_types::SandboxMode;
|
||||
use codex_protocol::permissions::NetworkSandboxPolicy;
|
||||
use codex_sandboxing::SandboxProcessLifetime;
|
||||
use codex_sandboxing::landlock::allow_network_for_proxy;
|
||||
use codex_sandboxing::landlock::create_linux_sandbox_command_args_for_permission_profile;
|
||||
#[cfg(target_os = "macos")]
|
||||
@@ -301,6 +302,7 @@ async fn run_command_under_sandbox(
|
||||
permission_profile_cwd.as_path(),
|
||||
use_legacy_landlock,
|
||||
allow_network_for_proxy(managed_network_requirements_enabled),
|
||||
SandboxProcessLifetime::TerminateWithParent,
|
||||
);
|
||||
spawn_debug_sandbox_child(
|
||||
codex_linux_sandbox_exe,
|
||||
|
||||
@@ -41,6 +41,7 @@ use codex_protocol::protocol::ExecOutputStream;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
use codex_sandboxing::SandboxCommand;
|
||||
use codex_sandboxing::SandboxManager;
|
||||
pub use codex_sandboxing::SandboxProcessLifetime;
|
||||
use codex_sandboxing::SandboxTransformRequest;
|
||||
use codex_sandboxing::SandboxType;
|
||||
use codex_sandboxing::SandboxablePreference;
|
||||
@@ -307,6 +308,7 @@ pub async fn process_exec_tool_call(
|
||||
sandbox_cwd,
|
||||
codex_linux_sandbox_exe,
|
||||
use_legacy_landlock,
|
||||
SandboxProcessLifetime::AllowDetachedChildren,
|
||||
)?;
|
||||
|
||||
// Route through the sandboxing module for a single, unified execution path.
|
||||
@@ -321,6 +323,7 @@ pub fn build_exec_request(
|
||||
sandbox_cwd: &AbsolutePathBuf,
|
||||
codex_linux_sandbox_exe: &Option<PathBuf>,
|
||||
use_legacy_landlock: bool,
|
||||
process_lifetime: SandboxProcessLifetime,
|
||||
) -> Result<ExecRequest> {
|
||||
let ExecParams {
|
||||
command,
|
||||
@@ -382,6 +385,7 @@ pub fn build_exec_request(
|
||||
sandbox_policy_cwd: sandbox_cwd,
|
||||
codex_linux_sandbox_exe: codex_linux_sandbox_exe.as_deref(),
|
||||
use_legacy_landlock,
|
||||
process_lifetime,
|
||||
windows_sandbox_level,
|
||||
windows_sandbox_private_desktop,
|
||||
})
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::spawn::StdioPolicy;
|
||||
use crate::spawn::spawn_child_async;
|
||||
use codex_network_proxy::NetworkProxy;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_sandboxing::SandboxProcessLifetime;
|
||||
use codex_sandboxing::landlock::CODEX_LINUX_SANDBOX_ARG0;
|
||||
use codex_sandboxing::landlock::allow_network_for_proxy;
|
||||
use codex_sandboxing::landlock::create_linux_sandbox_command_args_for_permission_profile;
|
||||
@@ -41,6 +42,7 @@ where
|
||||
sandbox_policy_cwd,
|
||||
use_legacy_landlock,
|
||||
allow_network_for_proxy(/*enforce_managed_network*/ false),
|
||||
SandboxProcessLifetime::AllowDetachedChildren,
|
||||
);
|
||||
let codex_linux_sandbox_exe = codex_linux_sandbox_exe.as_ref();
|
||||
// Preserve the helper alias when we already have it; otherwise force argv0
|
||||
|
||||
@@ -43,6 +43,7 @@ use codex_protocol::protocol::NetworkPolicyRuleAction;
|
||||
use codex_protocol::protocol::ReviewDecision;
|
||||
use codex_sandboxing::SandboxCommand;
|
||||
use codex_sandboxing::SandboxManager;
|
||||
use codex_sandboxing::SandboxProcessLifetime;
|
||||
use codex_sandboxing::SandboxTransformRequest;
|
||||
use codex_sandboxing::SandboxType;
|
||||
use codex_sandboxing::SandboxablePreference;
|
||||
@@ -925,6 +926,7 @@ impl CoreShellCommandExecutor {
|
||||
sandbox_policy_cwd: &self.sandbox_policy_cwd,
|
||||
codex_linux_sandbox_exe: self.codex_linux_sandbox_exe.as_deref(),
|
||||
use_legacy_landlock: self.use_legacy_landlock,
|
||||
process_lifetime: SandboxProcessLifetime::AllowDetachedChildren,
|
||||
windows_sandbox_level: self.windows_sandbox_level,
|
||||
windows_sandbox_private_desktop: false,
|
||||
})?;
|
||||
|
||||
@@ -21,6 +21,7 @@ use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::ReviewDecision;
|
||||
use codex_sandboxing::SandboxCommand;
|
||||
use codex_sandboxing::SandboxManager;
|
||||
use codex_sandboxing::SandboxProcessLifetime;
|
||||
use codex_sandboxing::SandboxTransformError;
|
||||
use codex_sandboxing::SandboxTransformRequest;
|
||||
use codex_sandboxing::SandboxType;
|
||||
@@ -409,6 +410,7 @@ impl<'a> SandboxAttempt<'a> {
|
||||
.codex_linux_sandbox_exe
|
||||
.map(std::path::PathBuf::as_path),
|
||||
use_legacy_landlock: self.use_legacy_landlock,
|
||||
process_lifetime: SandboxProcessLifetime::AllowDetachedChildren,
|
||||
windows_sandbox_level: self.windows_sandbox_level,
|
||||
windows_sandbox_private_desktop: self.windows_sandbox_private_desktop,
|
||||
})
|
||||
|
||||
@@ -11,6 +11,7 @@ use codex_protocol::permissions::NetworkSandboxPolicy;
|
||||
use codex_sandboxing::SandboxCommand;
|
||||
use codex_sandboxing::SandboxExecRequest;
|
||||
use codex_sandboxing::SandboxManager;
|
||||
use codex_sandboxing::SandboxProcessLifetime;
|
||||
use codex_sandboxing::SandboxTransformRequest;
|
||||
use codex_sandboxing::SandboxablePreference;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
@@ -111,6 +112,7 @@ impl FileSystemSandboxRunner {
|
||||
sandbox_policy_cwd: cwd.as_path(),
|
||||
codex_linux_sandbox_exe: self.runtime_paths.codex_linux_sandbox_exe.as_deref(),
|
||||
use_legacy_landlock: sandbox_context.use_legacy_landlock,
|
||||
process_lifetime: SandboxProcessLifetime::TerminateWithParent,
|
||||
windows_sandbox_level: sandbox_context.windows_sandbox_level,
|
||||
windows_sandbox_private_desktop: sandbox_context.windows_sandbox_private_desktop,
|
||||
})
|
||||
|
||||
@@ -22,6 +22,7 @@ async fn spawn_command_under_sandbox(
|
||||
) -> std::io::Result<Child> {
|
||||
use codex_core::exec::ExecCapturePolicy;
|
||||
use codex_core::exec::ExecParams;
|
||||
use codex_core::exec::SandboxProcessLifetime;
|
||||
use codex_core::exec::build_exec_request;
|
||||
use codex_core::sandboxing::SandboxPermissions;
|
||||
use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
@@ -46,6 +47,7 @@ async fn spawn_command_under_sandbox(
|
||||
sandbox_cwd,
|
||||
&codex_linux_sandbox_exe,
|
||||
/*use_legacy_landlock*/ false,
|
||||
SandboxProcessLifetime::AllowDetachedChildren,
|
||||
)
|
||||
.map_err(|err| io::Error::other(err.to_string()))?;
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::SandboxProcessLifetime;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use std::path::Path;
|
||||
|
||||
@@ -27,6 +28,7 @@ pub fn create_linux_sandbox_command_args_for_permission_profile(
|
||||
sandbox_policy_cwd: &Path,
|
||||
use_legacy_landlock: bool,
|
||||
allow_network_for_proxy: bool,
|
||||
process_lifetime: SandboxProcessLifetime,
|
||||
) -> Vec<String> {
|
||||
let permission_profile_json = serde_json::to_string(permission_profile)
|
||||
.unwrap_or_else(|err| panic!("failed to serialize permission profile: {err}"));
|
||||
@@ -53,7 +55,9 @@ pub fn create_linux_sandbox_command_args_for_permission_profile(
|
||||
if allow_network_for_proxy {
|
||||
linux_cmd.push("--allow-network-for-proxy".to_string());
|
||||
}
|
||||
linux_cmd.push("--allow-detached-children".to_string());
|
||||
if process_lifetime == SandboxProcessLifetime::AllowDetachedChildren {
|
||||
linux_cmd.push("--allow-detached-children".to_string());
|
||||
}
|
||||
linux_cmd.push("--".to_string());
|
||||
linux_cmd.extend(command);
|
||||
linux_cmd
|
||||
|
||||
@@ -65,6 +65,7 @@ fn permission_profile_flag_is_included() {
|
||||
cwd,
|
||||
/*use_legacy_landlock*/ true,
|
||||
/*allow_network_for_proxy*/ false,
|
||||
SandboxProcessLifetime::TerminateWithParent,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
@@ -77,6 +78,17 @@ fn permission_profile_flag_is_included() {
|
||||
.any(|window| window[0] == "--command-cwd" && window[1] == "/tmp/link"),
|
||||
true
|
||||
);
|
||||
assert!(!args.contains(&"--allow-detached-children".to_string()));
|
||||
|
||||
let args = create_linux_sandbox_command_args_for_permission_profile(
|
||||
vec!["/bin/true".to_string()],
|
||||
command_cwd,
|
||||
&permission_profile,
|
||||
cwd,
|
||||
/*use_legacy_landlock*/ true,
|
||||
/*allow_network_for_proxy*/ false,
|
||||
SandboxProcessLifetime::AllowDetachedChildren,
|
||||
);
|
||||
assert!(args.contains(&"--allow-detached-children".to_string()));
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ pub use bwrap::system_bwrap_warning;
|
||||
pub use manager::SandboxCommand;
|
||||
pub use manager::SandboxExecRequest;
|
||||
pub use manager::SandboxManager;
|
||||
pub use manager::SandboxProcessLifetime;
|
||||
pub use manager::SandboxTransformError;
|
||||
pub use manager::SandboxTransformRequest;
|
||||
pub use manager::SandboxType;
|
||||
|
||||
@@ -85,6 +85,13 @@ pub struct SandboxExecRequest {
|
||||
pub arg0: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
||||
pub enum SandboxProcessLifetime {
|
||||
#[default]
|
||||
TerminateWithParent,
|
||||
AllowDetachedChildren,
|
||||
}
|
||||
|
||||
/// Bundled arguments for sandbox transformation.
|
||||
///
|
||||
/// This keeps call sites self-documenting when several fields are optional.
|
||||
@@ -99,6 +106,7 @@ pub struct SandboxTransformRequest<'a> {
|
||||
pub sandbox_policy_cwd: &'a Path,
|
||||
pub codex_linux_sandbox_exe: Option<&'a Path>,
|
||||
pub use_legacy_landlock: bool,
|
||||
pub process_lifetime: SandboxProcessLifetime,
|
||||
pub windows_sandbox_level: WindowsSandboxLevel,
|
||||
pub windows_sandbox_private_desktop: bool,
|
||||
}
|
||||
@@ -178,6 +186,7 @@ impl SandboxManager {
|
||||
sandbox_policy_cwd,
|
||||
codex_linux_sandbox_exe,
|
||||
use_legacy_landlock,
|
||||
process_lifetime,
|
||||
windows_sandbox_level,
|
||||
windows_sandbox_private_desktop,
|
||||
} = request;
|
||||
@@ -232,6 +241,7 @@ impl SandboxManager {
|
||||
sandbox_policy_cwd,
|
||||
use_legacy_landlock,
|
||||
allow_proxy_network,
|
||||
process_lifetime,
|
||||
);
|
||||
let mut full_command = Vec::with_capacity(1 + args.len());
|
||||
full_command.push(os_string_to_command_component(exe.as_os_str().to_owned()));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use super::SandboxCommand;
|
||||
use super::SandboxManager;
|
||||
use super::SandboxProcessLifetime;
|
||||
use super::SandboxTransformRequest;
|
||||
use super::SandboxType;
|
||||
use super::SandboxablePreference;
|
||||
@@ -93,6 +94,7 @@ fn transform_preserves_unrestricted_file_system_policy_for_restricted_network()
|
||||
sandbox_policy_cwd: cwd.as_path(),
|
||||
codex_linux_sandbox_exe: None,
|
||||
use_legacy_landlock: false,
|
||||
process_lifetime: SandboxProcessLifetime::TerminateWithParent,
|
||||
windows_sandbox_level: WindowsSandboxLevel::Disabled,
|
||||
windows_sandbox_private_desktop: false,
|
||||
})
|
||||
@@ -144,6 +146,7 @@ fn transform_additional_permissions_enable_network_for_external_sandbox() {
|
||||
sandbox_policy_cwd: cwd.as_path(),
|
||||
codex_linux_sandbox_exe: None,
|
||||
use_legacy_landlock: false,
|
||||
process_lifetime: SandboxProcessLifetime::TerminateWithParent,
|
||||
windows_sandbox_level: WindowsSandboxLevel::Disabled,
|
||||
windows_sandbox_private_desktop: false,
|
||||
})
|
||||
@@ -212,6 +215,7 @@ fn transform_additional_permissions_preserves_denied_entries() {
|
||||
sandbox_policy_cwd: cwd.as_path(),
|
||||
codex_linux_sandbox_exe: None,
|
||||
use_legacy_landlock: false,
|
||||
process_lifetime: SandboxProcessLifetime::TerminateWithParent,
|
||||
windows_sandbox_level: WindowsSandboxLevel::Disabled,
|
||||
windows_sandbox_private_desktop: false,
|
||||
})
|
||||
@@ -265,6 +269,7 @@ fn transform_linux_seccomp_request(
|
||||
sandbox_policy_cwd: cwd.as_path(),
|
||||
codex_linux_sandbox_exe: Some(codex_linux_sandbox_exe),
|
||||
use_legacy_landlock: false,
|
||||
process_lifetime: SandboxProcessLifetime::TerminateWithParent,
|
||||
windows_sandbox_level: WindowsSandboxLevel::Disabled,
|
||||
windows_sandbox_private_desktop: false,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user