sandboxing: intersect permission profiles semantically

This commit is contained in:
Michael Bolin
2026-04-17 12:31:56 -07:00
parent 346920b89a
commit af87f2160e
8 changed files with 261 additions and 29 deletions
@@ -226,6 +226,7 @@ async fn effective_patch_permissions(
);
let effective_additional_permissions = apply_granted_turn_permissions(
session,
turn.cwd.as_path(),
crate::sandboxing::SandboxPermissions::UseDefault,
write_permissions_for_paths(&file_paths, &file_system_sandbox_policy, &turn.cwd),
)
+2 -1
View File
@@ -169,6 +169,7 @@ pub(super) fn implicit_granted_permissions(
pub(super) async fn apply_granted_turn_permissions(
session: &Session,
cwd: &std::path::Path,
sandbox_permissions: SandboxPermissions,
additional_permissions: Option<PermissionProfile>,
) -> EffectiveAdditionalPermissions {
@@ -192,7 +193,7 @@ pub(super) async fn apply_granted_turn_permissions(
);
let permissions_preapproved = match (effective_permissions.as_ref(), granted_permissions) {
(Some(effective_permissions), Some(granted_permissions)) => {
intersect_permission_profiles(effective_permissions.clone(), granted_permissions)
intersect_permission_profiles(effective_permissions.clone(), granted_permissions, cwd)
== *effective_permissions
}
_ => false,
@@ -424,6 +424,7 @@ impl ShellHandler {
let requested_additional_permissions = additional_permissions.clone();
let effective_additional_permissions = apply_granted_turn_permissions(
session.as_ref(),
turn.cwd.as_path(),
exec_params.sandbox_permissions,
additional_permissions,
)
@@ -230,6 +230,7 @@ impl ToolHandler for UnifiedExecHandler {
let requested_additional_permissions = additional_permissions.clone();
let effective_additional_permissions = apply_granted_turn_permissions(
context.session.as_ref(),
context.turn.cwd.as_path(),
sandbox_permissions,
additional_permissions,
)
@@ -1586,17 +1586,17 @@ async fn partial_request_permissions_grants_do_not_preapprove_new_permissions()
.unwrap_or_else(|| panic!("expected filesystem permissions"));
let (approval_reads, approval_writes) = approval_file_system
.legacy_read_write_roots()
.unwrap_or_default();
.unwrap_or_else(|| panic!("expected legacy-compatible permissions"));
assert!(approval_reads.as_ref().is_none_or(Vec::is_empty));
let mut approval_writes = approval_writes.unwrap_or_default();
approval_writes.sort_by_key(|path| path.display().to_string());
let (_expected_reads, expected_writes) = merged_permissions
let (_, expected_writes) = merged_permissions
.file_system
.unwrap_or_else(|| panic!("expected merged filesystem permissions"))
.legacy_read_write_roots()
.unwrap_or_default();
.unwrap_or_else(|| panic!("expected legacy-compatible permissions"));
let mut expected_writes = expected_writes.unwrap_or_default();
expected_writes.sort_by_key(|path| path.display().to_string());