codex: address remaining sandbox review feedback (#16736)

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
starr-openai
2026-04-07 14:30:20 -07:00
parent b61a0d0976
commit 0695fe1d02
17 changed files with 173 additions and 216 deletions

View File

@@ -40,7 +40,6 @@ use codex_protocol::protocol::ExecOutputStream;
use codex_protocol::protocol::SandboxPolicy;
use codex_sandboxing::SandboxCommand;
use codex_sandboxing::SandboxManager;
use codex_sandboxing::SandboxTransformRequest;
use codex_sandboxing::SandboxType;
use codex_sandboxing::SandboxablePreference;
use codex_utils_absolute_path::AbsolutePathBuf;
@@ -284,20 +283,20 @@ pub fn build_exec_request(
capture_policy,
};
let mut exec_req = manager
.transform(SandboxTransformRequest {
.transform(
command,
policy: sandbox_policy,
file_system_policy: file_system_sandbox_policy,
network_policy: network_sandbox_policy,
sandbox: sandbox_type,
sandbox_policy,
file_system_sandbox_policy,
network_sandbox_policy,
sandbox_type,
enforce_managed_network,
network: network.as_ref(),
sandbox_policy_cwd: sandbox_cwd,
codex_linux_sandbox_exe: codex_linux_sandbox_exe.as_ref(),
network.as_ref(),
sandbox_cwd,
codex_linux_sandbox_exe.as_ref(),
use_legacy_landlock,
windows_sandbox_level,
windows_sandbox_private_desktop,
})
)
.map(|request| ExecRequest::from_sandbox_exec_request(request, options))
.map_err(CodexErr::from)?;
exec_req.windows_restricted_token_filesystem_overlay =

View File

@@ -43,7 +43,6 @@ use crate::tools::ToolRouter;
use crate::tools::context::SharedTurnDiffTracker;
use codex_sandboxing::SandboxCommand;
use codex_sandboxing::SandboxManager;
use codex_sandboxing::SandboxTransformRequest;
use codex_sandboxing::SandboxablePreference;
use codex_tools::ToolSpec;
use codex_utils_output_truncation::TruncationPolicy;
@@ -1059,23 +1058,20 @@ impl JsReplManager {
capture_policy: ExecCapturePolicy::ShellTool,
};
let exec_env = sandbox
.transform(SandboxTransformRequest {
.transform(
command,
policy: &turn.sandbox_policy,
file_system_policy: &turn.file_system_sandbox_policy,
network_policy: turn.network_sandbox_policy,
sandbox: sandbox_type,
enforce_managed_network: has_managed_network_requirements,
network: None,
sandbox_policy_cwd: &turn.cwd,
codex_linux_sandbox_exe: turn.codex_linux_sandbox_exe.as_ref(),
use_legacy_landlock: turn.features.use_legacy_landlock(),
windows_sandbox_level: turn.windows_sandbox_level,
windows_sandbox_private_desktop: turn
.config
.permissions
.windows_sandbox_private_desktop,
})
&turn.sandbox_policy,
&turn.file_system_sandbox_policy,
turn.network_sandbox_policy,
sandbox_type,
has_managed_network_requirements,
None,
&turn.cwd,
turn.codex_linux_sandbox_exe.as_ref(),
turn.features.use_legacy_landlock(),
turn.windows_sandbox_level,
turn.config.permissions.windows_sandbox_private_desktop,
)
.map(|request| {
crate::sandboxing::ExecRequest::from_sandbox_exec_request(request, options)
})

View File

@@ -34,7 +34,6 @@ use codex_protocol::protocol::ReviewDecision;
use codex_protocol::protocol::SandboxPolicy;
use codex_sandboxing::SandboxCommand;
use codex_sandboxing::SandboxManager;
use codex_sandboxing::SandboxTransformRequest;
use codex_sandboxing::SandboxType;
use codex_sandboxing::SandboxablePreference;
use codex_shell_command::bash::parse_shell_lc_plain_commands;
@@ -835,20 +834,20 @@ impl CoreShellCommandExecutor {
expiration: ExecExpiration::DefaultTimeout,
capture_policy: ExecCapturePolicy::ShellTool,
};
let exec_request = sandbox_manager.transform(SandboxTransformRequest {
let exec_request = sandbox_manager.transform(
command,
policy: sandbox_policy,
file_system_policy: file_system_sandbox_policy,
network_policy: network_sandbox_policy,
sandbox_policy,
file_system_sandbox_policy,
network_sandbox_policy,
sandbox,
enforce_managed_network: self.network.is_some(),
network: self.network.as_ref(),
sandbox_policy_cwd: &self.sandbox_policy_cwd,
codex_linux_sandbox_exe: self.codex_linux_sandbox_exe.as_ref(),
use_legacy_landlock: self.use_legacy_landlock,
windows_sandbox_level: self.windows_sandbox_level,
windows_sandbox_private_desktop: false,
})?;
self.network.is_some(),
self.network.as_ref(),
&self.sandbox_policy_cwd,
self.codex_linux_sandbox_exe.as_ref(),
self.use_legacy_landlock,
self.windows_sandbox_level,
false,
)?;
let mut exec_request =
crate::sandboxing::ExecRequest::from_sandbox_exec_request(exec_request, options);
if let Some(network) = exec_request.network.as_ref() {

View File

@@ -86,12 +86,12 @@ pub struct UnifiedExecRuntime<'a> {
fn build_remote_exec_sandbox_config(
attempt: &SandboxAttempt<'_>,
additional_permissions: Option<PermissionProfile>,
) -> Option<SandboxLaunchConfig> {
) -> SandboxLaunchConfig {
if matches!(attempt.sandbox, codex_sandboxing::SandboxType::None) {
return None;
return SandboxLaunchConfig::no_sandbox(attempt.sandbox_cwd.to_path_buf());
}
Some(SandboxLaunchConfig {
SandboxLaunchConfig {
sandbox: attempt.sandbox,
policy: attempt.policy.clone(),
file_system_policy: attempt.file_system_policy.clone(),
@@ -102,7 +102,7 @@ fn build_remote_exec_sandbox_config(
windows_sandbox_level: attempt.windows_sandbox_level,
windows_sandbox_private_desktop: attempt.windows_sandbox_private_desktop,
use_legacy_landlock: attempt.use_legacy_landlock,
})
}
}
impl<'a> UnifiedExecRuntime<'a> {
@@ -248,12 +248,6 @@ impl<'a> ToolRuntime<UnifiedExecRequest, UnifiedExecProcess> for UnifiedExecRunt
.to_string(),
));
}
if req.network.is_some() {
return Err(ToolError::Rejected(
"unified_exec managed-network is not supported when exec_server_url is configured"
.to_string(),
));
}
let exec_params = codex_exec_server::ExecParams {
process_id: req.process_id.to_string().into(),
argv: command,

View File

@@ -24,7 +24,6 @@ use codex_protocol::protocol::SandboxPolicy;
use codex_sandboxing::SandboxCommand;
use codex_sandboxing::SandboxManager;
use codex_sandboxing::SandboxTransformError;
use codex_sandboxing::SandboxTransformRequest;
use codex_sandboxing::SandboxType;
use codex_sandboxing::SandboxablePreference;
use futures::Future;
@@ -339,20 +338,20 @@ impl<'a> SandboxAttempt<'a> {
network: Option<&NetworkProxy>,
) -> Result<crate::sandboxing::ExecRequest, SandboxTransformError> {
self.manager
.transform(SandboxTransformRequest {
.transform(
command,
policy: self.policy,
file_system_policy: self.file_system_policy,
network_policy: self.network_policy,
sandbox: self.sandbox,
enforce_managed_network: self.enforce_managed_network,
self.policy,
self.file_system_policy,
self.network_policy,
self.sandbox,
self.enforce_managed_network,
network,
sandbox_policy_cwd: self.sandbox_cwd,
codex_linux_sandbox_exe: self.codex_linux_sandbox_exe,
use_legacy_landlock: self.use_legacy_landlock,
windows_sandbox_level: self.windows_sandbox_level,
windows_sandbox_private_desktop: self.windows_sandbox_private_desktop,
})
self.sandbox_cwd,
self.codex_linux_sandbox_exe,
self.use_legacy_landlock,
self.windows_sandbox_level,
self.windows_sandbox_private_desktop,
)
.map(|request| {
crate::sandboxing::ExecRequest::from_sandbox_exec_request(request, options)
})

View File

@@ -12,7 +12,7 @@
//! Flow at a glance (open process)
//! 1) Build a small request `{ command, cwd }`.
//! 2) Orchestrator: approval (bypass/cache/prompt) → select sandbox → run.
//! 3) Runtime: transform `SandboxTransformRequest` -> `ExecRequest` -> spawn PTY.
//! 3) Runtime: transform sandbox config -> `ExecRequest` -> spawn PTY.
//! 4) If denial, orchestrator retries with `SandboxType::None`.
//! 5) Process handle is returned with streaming output + metadata.
//!

View File

@@ -609,7 +609,7 @@ impl UnifiedExecProcessManager {
env: env.env.clone(),
tty,
arg0: env.arg0.clone(),
sandbox: None,
sandbox: codex_sandboxing::SandboxLaunchConfig::no_sandbox(env.cwd.clone()),
})
.await
.map_err(|err| UnifiedExecError::create_process(err.to_string()))?;

View File

@@ -160,6 +160,7 @@ mod tests {
use super::Environment;
use super::EnvironmentManager;
use crate::ProcessId;
use codex_sandboxing::SandboxLaunchConfig;
use pretty_assertions::assert_eq;
#[tokio::test]
@@ -202,7 +203,9 @@ mod tests {
env: Default::default(),
tty: false,
arg0: None,
sandbox: None,
sandbox: SandboxLaunchConfig::no_sandbox(
std::env::current_dir().expect("read current dir"),
),
})
.await
.expect("start process");

View File

@@ -9,14 +9,9 @@ use std::time::Duration;
use async_trait::async_trait;
use codex_app_server_protocol::JSONRPCErrorError;
use codex_protocol::config_types::WindowsSandboxLevel;
use codex_protocol::permissions::FileSystemSandboxPolicy;
use codex_protocol::permissions::NetworkSandboxPolicy;
use codex_protocol::protocol::SandboxPolicy;
use codex_sandboxing::SandboxCommand;
use codex_sandboxing::SandboxExecRequest;
use codex_sandboxing::SandboxType;
use codex_sandboxing::landlock::CODEX_LINUX_SANDBOX_ARG0;
use codex_utils_pty::ExecCommandSession;
use codex_utils_pty::TerminalSize;
use tokio::sync::Mutex;
@@ -110,14 +105,8 @@ struct ExecServerRuntimeConfig {
impl ExecServerRuntimeConfig {
fn detect() -> Self {
let env_path = std::env::var_os("CODEX_LINUX_SANDBOX_EXE").map(PathBuf::from);
let sibling_path = std::env::current_exe().ok().and_then(|current_exe| {
current_exe
.parent()
.map(|parent| parent.join(CODEX_LINUX_SANDBOX_ARG0))
.filter(|candidate| candidate.exists())
});
Self {
codex_linux_sandbox_exe: env_path.or(sibling_path),
codex_linux_sandbox_exe: env_path,
}
}
}
@@ -523,29 +512,14 @@ fn prepare_exec_launch(
params: &ExecParams,
runtime: &ExecServerRuntimeConfig,
) -> Result<SandboxExecRequest, JSONRPCErrorError> {
let Some(sandbox) = params.sandbox.as_ref() else {
return Ok(SandboxExecRequest {
command: params.argv.clone(),
cwd: params.cwd.clone(),
env: params.env.clone(),
arg0: params.arg0.clone(),
network: None,
sandbox: SandboxType::None,
windows_sandbox_level: WindowsSandboxLevel::Disabled,
windows_sandbox_private_desktop: false,
sandbox_policy: SandboxPolicy::DangerFullAccess,
file_system_sandbox_policy: FileSystemSandboxPolicy::unrestricted(),
network_sandbox_policy: NetworkSandboxPolicy::Enabled,
});
};
let command = build_sandbox_command(
&params.argv,
params.cwd.as_path(),
&params.env,
sandbox.additional_permissions.clone(),
params.sandbox.additional_permissions.clone(),
)?;
sandbox
params
.sandbox
.transform(
command,
// TODO: Thread managed-network proxy state across exec-server so

View File

@@ -62,7 +62,7 @@ pub struct ExecParams {
pub env: HashMap<String, String>,
pub tty: bool,
pub arg0: Option<String>,
pub sandbox: Option<SandboxLaunchConfig>,
pub sandbox: SandboxLaunchConfig,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]

View File

@@ -1,7 +1,6 @@
use std::sync::Arc;
use async_trait::async_trait;
use codex_sandboxing::SandboxType;
use tokio::sync::watch;
use tracing::trace;
@@ -35,10 +34,7 @@ impl RemoteProcess {
impl ExecBackend for RemoteProcess {
async fn start(&self, params: ExecParams) -> Result<StartedExecProcess, ExecServerError> {
let process_id = params.process_id.clone();
let sandbox_type = params
.sandbox
.as_ref()
.map_or(SandboxType::None, |sandbox| sandbox.sandbox);
let sandbox_type = params.sandbox.sandbox;
let session = self.client.register_session(&process_id).await?;
match self.client.exec(params).await {
Ok(_) => {}

View File

@@ -12,6 +12,7 @@ use crate::protocol::InitializeResponse;
use crate::protocol::TerminateParams;
use crate::protocol::TerminateResponse;
use crate::rpc::RpcNotificationSender;
use codex_sandboxing::SandboxLaunchConfig;
fn exec_params(process_id: &str) -> ExecParams {
let mut env = HashMap::new();
@@ -29,7 +30,7 @@ fn exec_params(process_id: &str) -> ExecParams {
env,
tty: false,
arg0: None,
sandbox: None,
sandbox: SandboxLaunchConfig::no_sandbox(std::env::current_dir().expect("cwd")),
}
}

View File

@@ -61,7 +61,9 @@ async fn assert_exec_process_starts_and_exits(use_remote: bool) -> Result<()> {
env: Default::default(),
tty: false,
arg0: None,
sandbox: None,
sandbox: SandboxLaunchConfig::no_sandbox(
std::env::current_dir().expect("read current dir"),
),
})
.await?;
assert_eq!(session.process.process_id().as_str(), "proc-1");
@@ -138,7 +140,9 @@ async fn assert_exec_process_streams_output(use_remote: bool) -> Result<()> {
env: Default::default(),
tty: false,
arg0: None,
sandbox: None,
sandbox: SandboxLaunchConfig::no_sandbox(
std::env::current_dir().expect("read current dir"),
),
})
.await?;
assert_eq!(session.process.process_id().as_str(), process_id);
@@ -168,7 +172,7 @@ async fn assert_exec_process_write_then_read(use_remote: bool) -> Result<()> {
env: Default::default(),
tty: true,
arg0: None,
sandbox: None,
sandbox: SandboxLaunchConfig::no_sandbox(std::env::current_dir().expect("read current dir")),
})
.await?;
assert_eq!(session.process.process_id().as_str(), process_id);
@@ -205,7 +209,9 @@ async fn assert_exec_process_preserves_queued_events_before_subscribe(
env: Default::default(),
tty: false,
arg0: None,
sandbox: None,
sandbox: SandboxLaunchConfig::no_sandbox(
std::env::current_dir().expect("read current dir"),
),
})
.await?;
@@ -306,7 +312,9 @@ async fn remote_exec_process_reports_transport_disconnect() -> Result<()> {
env: Default::default(),
tty: false,
arg0: None,
sandbox: None,
sandbox: SandboxLaunchConfig::no_sandbox(
std::env::current_dir().expect("read current dir"),
),
})
.await?;

View File

@@ -15,7 +15,6 @@ pub use manager::SandboxExecRequest;
pub use manager::SandboxLaunchConfig;
pub use manager::SandboxManager;
pub use manager::SandboxTransformError;
pub use manager::SandboxTransformRequest;
pub use manager::SandboxType;
pub use manager::SandboxablePreference;
pub use manager::get_platform_sandbox;

View File

@@ -65,26 +65,41 @@ pub struct SandboxLaunchConfig {
}
impl SandboxLaunchConfig {
pub fn no_sandbox(sandbox_policy_cwd: PathBuf) -> Self {
Self {
sandbox: SandboxType::None,
policy: SandboxPolicy::DangerFullAccess,
file_system_policy: FileSystemSandboxPolicy::unrestricted(),
network_policy: NetworkSandboxPolicy::Enabled,
sandbox_policy_cwd,
additional_permissions: None,
enforce_managed_network: false,
windows_sandbox_level: WindowsSandboxLevel::Disabled,
windows_sandbox_private_desktop: false,
use_legacy_landlock: false,
}
}
pub fn transform(
&self,
command: SandboxCommand,
network: Option<&NetworkProxy>,
codex_linux_sandbox_exe: Option<&PathBuf>,
) -> Result<SandboxExecRequest, SandboxTransformError> {
SandboxManager::new().transform(SandboxTransformRequest {
SandboxManager::new().transform(
command,
policy: &self.policy,
file_system_policy: &self.file_system_policy,
network_policy: self.network_policy,
sandbox: self.sandbox,
enforce_managed_network: self.enforce_managed_network,
&self.policy,
&self.file_system_policy,
self.network_policy,
self.sandbox,
self.enforce_managed_network,
network,
sandbox_policy_cwd: self.sandbox_policy_cwd.as_path(),
self.sandbox_policy_cwd.as_path(),
codex_linux_sandbox_exe,
use_legacy_landlock: self.use_legacy_landlock,
windows_sandbox_level: self.windows_sandbox_level,
windows_sandbox_private_desktop: self.windows_sandbox_private_desktop,
})
self.use_legacy_landlock,
self.windows_sandbox_level,
self.windows_sandbox_private_desktop,
)
}
}
@@ -128,26 +143,6 @@ pub struct SandboxExecRequest {
pub arg0: Option<String>,
}
/// Bundled arguments for sandbox transformation.
///
/// This keeps call sites self-documenting when several fields are optional.
pub struct SandboxTransformRequest<'a> {
pub command: SandboxCommand,
pub policy: &'a SandboxPolicy,
pub file_system_policy: &'a FileSystemSandboxPolicy,
pub network_policy: NetworkSandboxPolicy,
pub sandbox: SandboxType,
pub enforce_managed_network: bool,
// TODO(viyatb): Evaluate switching this to Option<Arc<NetworkProxy>>
// to make shared ownership explicit across runtime/sandbox plumbing.
pub network: Option<&'a NetworkProxy>,
pub sandbox_policy_cwd: &'a Path,
pub codex_linux_sandbox_exe: Option<&'a PathBuf>,
pub use_legacy_landlock: bool,
pub windows_sandbox_level: WindowsSandboxLevel,
pub windows_sandbox_private_desktop: bool,
}
#[derive(Debug)]
pub enum SandboxTransformError {
MissingLinuxSandboxExecutable,
@@ -208,22 +203,19 @@ impl SandboxManager {
pub fn transform(
&self,
request: SandboxTransformRequest<'_>,
mut command: SandboxCommand,
policy: &SandboxPolicy,
file_system_policy: &FileSystemSandboxPolicy,
network_policy: NetworkSandboxPolicy,
sandbox: SandboxType,
enforce_managed_network: bool,
network: Option<&NetworkProxy>,
sandbox_policy_cwd: &Path,
codex_linux_sandbox_exe: Option<&PathBuf>,
use_legacy_landlock: bool,
windows_sandbox_level: WindowsSandboxLevel,
windows_sandbox_private_desktop: bool,
) -> Result<SandboxExecRequest, SandboxTransformError> {
let SandboxTransformRequest {
mut command,
policy,
file_system_policy,
network_policy,
sandbox,
enforce_managed_network,
network,
sandbox_policy_cwd,
codex_linux_sandbox_exe,
use_legacy_landlock,
windows_sandbox_level,
windows_sandbox_private_desktop,
} = request;
let additional_permissions = command.additional_permissions.take();
let EffectiveSandboxPermissions {
sandbox_policy: effective_policy,

View File

@@ -1,6 +1,5 @@
use super::SandboxCommand;
use super::SandboxManager;
use super::SandboxTransformRequest;
use super::SandboxType;
use super::SandboxablePreference;
use super::get_platform_sandbox;
@@ -76,28 +75,28 @@ fn transform_preserves_unrestricted_file_system_policy_for_restricted_network()
let manager = SandboxManager::new();
let cwd = std::env::current_dir().expect("current dir");
let exec_request = manager
.transform(SandboxTransformRequest {
command: SandboxCommand {
.transform(
SandboxCommand {
program: "true".into(),
args: Vec::new(),
cwd: cwd.clone(),
env: HashMap::new(),
additional_permissions: None,
},
policy: &SandboxPolicy::ExternalSandbox {
&SandboxPolicy::ExternalSandbox {
network_access: NetworkAccess::Restricted,
},
file_system_policy: &FileSystemSandboxPolicy::unrestricted(),
network_policy: NetworkSandboxPolicy::Restricted,
sandbox: SandboxType::None,
enforce_managed_network: false,
network: None,
sandbox_policy_cwd: cwd.as_path(),
codex_linux_sandbox_exe: None,
use_legacy_landlock: false,
windows_sandbox_level: WindowsSandboxLevel::Disabled,
windows_sandbox_private_desktop: false,
})
&FileSystemSandboxPolicy::unrestricted(),
NetworkSandboxPolicy::Restricted,
SandboxType::None,
false,
None,
cwd.as_path(),
None,
false,
WindowsSandboxLevel::Disabled,
false,
)
.expect("transform");
assert_eq!(
@@ -120,8 +119,8 @@ fn transform_additional_permissions_enable_network_for_external_sandbox() {
)
.expect("absolute temp dir");
let exec_request = manager
.transform(SandboxTransformRequest {
command: SandboxCommand {
.transform(
SandboxCommand {
program: "true".into(),
args: Vec::new(),
cwd: cwd.clone(),
@@ -136,20 +135,20 @@ fn transform_additional_permissions_enable_network_for_external_sandbox() {
}),
}),
},
policy: &SandboxPolicy::ExternalSandbox {
&SandboxPolicy::ExternalSandbox {
network_access: NetworkAccess::Restricted,
},
file_system_policy: &FileSystemSandboxPolicy::unrestricted(),
network_policy: NetworkSandboxPolicy::Restricted,
sandbox: SandboxType::None,
enforce_managed_network: false,
network: None,
sandbox_policy_cwd: cwd.as_path(),
codex_linux_sandbox_exe: None,
use_legacy_landlock: false,
windows_sandbox_level: WindowsSandboxLevel::Disabled,
windows_sandbox_private_desktop: false,
})
&FileSystemSandboxPolicy::unrestricted(),
NetworkSandboxPolicy::Restricted,
SandboxType::None,
false,
None,
cwd.as_path(),
None,
false,
WindowsSandboxLevel::Disabled,
false,
)
.expect("transform");
assert_eq!(
@@ -176,8 +175,8 @@ fn transform_additional_permissions_preserves_denied_entries() {
let allowed_path = workspace_root.join("allowed").expect("allowed path");
let denied_path = workspace_root.join("denied").expect("denied path");
let exec_request = manager
.transform(SandboxTransformRequest {
command: SandboxCommand {
.transform(
SandboxCommand {
program: "true".into(),
args: Vec::new(),
cwd: cwd.clone(),
@@ -190,11 +189,11 @@ fn transform_additional_permissions_preserves_denied_entries() {
..Default::default()
}),
},
policy: &SandboxPolicy::ReadOnly {
&SandboxPolicy::ReadOnly {
access: ReadOnlyAccess::FullAccess,
network_access: false,
},
file_system_policy: &FileSystemSandboxPolicy::restricted(vec![
&FileSystemSandboxPolicy::restricted(vec![
FileSystemSandboxEntry {
path: FileSystemPath::Special {
value: FileSystemSpecialPath::Root,
@@ -208,16 +207,16 @@ fn transform_additional_permissions_preserves_denied_entries() {
access: FileSystemAccessMode::None,
},
]),
network_policy: NetworkSandboxPolicy::Restricted,
sandbox: SandboxType::None,
enforce_managed_network: false,
network: None,
sandbox_policy_cwd: cwd.as_path(),
codex_linux_sandbox_exe: None,
use_legacy_landlock: false,
windows_sandbox_level: WindowsSandboxLevel::Disabled,
windows_sandbox_private_desktop: false,
})
NetworkSandboxPolicy::Restricted,
SandboxType::None,
false,
None,
cwd.as_path(),
None,
false,
WindowsSandboxLevel::Disabled,
false,
)
.expect("transform");
assert_eq!(
@@ -252,26 +251,26 @@ fn transform_linux_seccomp_request(
let manager = SandboxManager::new();
let cwd = std::env::current_dir().expect("current dir");
manager
.transform(SandboxTransformRequest {
command: SandboxCommand {
.transform(
SandboxCommand {
program: "true".into(),
args: Vec::new(),
cwd: cwd.clone(),
env: HashMap::new(),
additional_permissions: None,
},
policy: &SandboxPolicy::DangerFullAccess,
file_system_policy: &FileSystemSandboxPolicy::unrestricted(),
network_policy: NetworkSandboxPolicy::Enabled,
sandbox: SandboxType::LinuxSeccomp,
enforce_managed_network: false,
network: None,
sandbox_policy_cwd: cwd.as_path(),
codex_linux_sandbox_exe: Some(codex_linux_sandbox_exe),
use_legacy_landlock: false,
windows_sandbox_level: WindowsSandboxLevel::Disabled,
windows_sandbox_private_desktop: false,
})
&SandboxPolicy::DangerFullAccess,
&FileSystemSandboxPolicy::unrestricted(),
NetworkSandboxPolicy::Enabled,
SandboxType::LinuxSeccomp,
false,
None,
cwd.as_path(),
Some(codex_linux_sandbox_exe),
false,
WindowsSandboxLevel::Disabled,
false,
)
.expect("transform")
}

View File

@@ -27,11 +27,9 @@ use tempfile::TempDir;
fn assert_seatbelt_denied(stderr: &[u8], path: &Path) {
let stderr = String::from_utf8_lossy(stderr);
let path_display = path.display().to_string();
let denied_path = stderr.contains(&path_display);
let denied_operation = stderr.contains("Operation not permitted");
assert!(
(denied_path && denied_operation)
(stderr.contains(&path.display().to_string())
&& stderr.contains("Operation not permitted"))
|| stderr.contains("sandbox-exec: sandbox_apply: Operation not permitted"),
"unexpected stderr: {stderr}"
);