sandboxing: preserve denied paths when widening permissions

This commit is contained in:
Michael Bolin
2026-03-06 15:22:20 -08:00
parent 9b81b65552
commit 8883fe0ff6
2 changed files with 16 additions and 33 deletions

View File

@@ -29,6 +29,7 @@ use crate::sandboxing::CommandSpec;
use crate::sandboxing::ExecRequest;
use crate::sandboxing::SandboxManager;
use crate::sandboxing::SandboxPermissions;
use crate::sandboxing::should_require_platform_sandbox;
use crate::spawn::SpawnChildRequest;
use crate::spawn::StdioPolicy;
use crate::spawn::spawn_child_async;
@@ -165,22 +166,17 @@ pub async fn process_exec_tool_call(
) -> Result<ExecToolCallOutput> {
let windows_sandbox_level = params.windows_sandbox_level;
let enforce_managed_network = params.network.is_some();
let sandbox_type = match file_system_sandbox_policy.kind {
FileSystemSandboxKind::Unrestricted | FileSystemSandboxKind::ExternalSandbox => {
if enforce_managed_network {
get_platform_sandbox(
windows_sandbox_level
!= codex_protocol::config_types::WindowsSandboxLevel::Disabled,
)
.unwrap_or(SandboxType::None)
} else {
SandboxType::None
}
}
_ => get_platform_sandbox(
let sandbox_type = if should_require_platform_sandbox(
file_system_sandbox_policy,
network_sandbox_policy,
enforce_managed_network,
) {
get_platform_sandbox(
windows_sandbox_level != codex_protocol::config_types::WindowsSandboxLevel::Disabled,
)
.unwrap_or(SandboxType::None),
.unwrap_or(SandboxType::None)
} else {
SandboxType::None
};
tracing::debug!("Sandbox type: {sandbox_type:?}");

View File

@@ -35,7 +35,6 @@ use codex_protocol::permissions::FileSystemPath;
use codex_protocol::permissions::FileSystemSandboxEntry;
use codex_protocol::permissions::FileSystemSandboxKind;
use codex_protocol::permissions::FileSystemSandboxPolicy;
use codex_protocol::permissions::FileSystemSpecialPath;
use codex_protocol::permissions::NetworkSandboxPolicy;
use codex_protocol::protocol::NetworkAccess;
use codex_protocol::protocol::ReadOnlyAccess;
@@ -215,7 +214,6 @@ fn additional_permission_roots(
)
}
#[cfg_attr(not(test), allow(dead_code))]
fn merge_file_system_policy_with_additional_permissions(
file_system_policy: &FileSystemSandboxPolicy,
extra_reads: Vec<AbsolutePathBuf>,
@@ -249,7 +247,6 @@ fn merge_file_system_policy_with_additional_permissions(
}
}
}
fn merge_read_only_access_with_additional_reads(
read_only_access: &ReadOnlyAccess,
extra_reads: Vec<AbsolutePathBuf>,
@@ -369,18 +366,10 @@ pub(crate) fn should_require_platform_sandbox(
}
match file_system_policy.kind {
FileSystemSandboxKind::Restricted => !file_system_policy.entries.iter().any(|entry| {
entry.access == FileSystemAccessMode::Write
&& matches!(
&entry.path,
FileSystemPath::Special { value }
if matches!(value, FileSystemSpecialPath::Root)
)
}),
FileSystemSandboxKind::Restricted => !file_system_policy.has_full_disk_write_access(),
FileSystemSandboxKind::Unrestricted | FileSystemSandboxKind::ExternalSandbox => false,
}
}
#[derive(Default)]
pub struct SandboxManager;
@@ -462,13 +451,11 @@ impl SandboxManager {
if extra_reads.is_empty() && extra_writes.is_empty() {
file_system_policy.clone()
} else {
match file_system_policy.kind {
FileSystemSandboxKind::Restricted => {
FileSystemSandboxPolicy::from(&effective_policy)
}
FileSystemSandboxKind::Unrestricted
| FileSystemSandboxKind::ExternalSandbox => file_system_policy.clone(),
}
merge_file_system_policy_with_additional_permissions(
file_system_policy,
extra_reads,
extra_writes,
)
};
let network_sandbox_policy = NetworkSandboxPolicy::from(&effective_policy);
(file_system_sandbox_policy, network_sandbox_policy)