mirror of
https://github.com/openai/codex.git
synced 2026-09-09 15:58:47 +00:00
codex: address remaining sandbox review feedback (#16736)
Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
@@ -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 =
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
@@ -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.
|
||||
//!
|
||||
|
||||
@@ -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()))?;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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(
|
||||
¶ms.argv,
|
||||
params.cwd.as_path(),
|
||||
¶ms.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
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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(_) => {}
|
||||
|
||||
@@ -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")),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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?;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
|
||||
@@ -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}"
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user