mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
permissions: migrate approval and sandbox consumers to profiles (#19393)
## Why Runtime decisions should not infer permissions from the lossy legacy sandbox projection once `PermissionProfile` is available. In particular, `Disabled` and `External` need to remain distinct, and managed profiles with split filesystem or deny-read rules should not be collapsed before approval, network, safety, or analytics code makes decisions. ## What Changed - Changes managed network proxy setup and network approval logic to use `PermissionProfile` when deciding whether a managed sandbox is active. - Migrates patch safety, Guardian/user-shell approval paths, Landlock helper setup, analytics sandbox classification, and selected turn/session code to profile-backed permissions. - Validates command-level profile overrides against the constrained `PermissionProfile` rather than a strict `SandboxPolicy` round trip. - Preserves configured deny-read restrictions when command profiles are narrowed. - Adds coverage for profile-backed trust, network proxy/approval behavior, patch safety, analytics classification, and command-profile narrowing. ## Verification - `cargo test -p codex-core direct_write_roots` - `cargo test -p codex-core runtime_roots_to_legacy_projection` - `cargo test -p codex-app-server requested_permissions_trust_project_uses_permission_profile_intent` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/19393). * #19395 * #19394 * __->__ #19393
This commit is contained in:
@@ -21,11 +21,11 @@ use codex_network_proxy::NetworkProxy;
|
||||
use codex_protocol::approvals::NetworkApprovalContext;
|
||||
use codex_protocol::approvals::NetworkApprovalProtocol;
|
||||
use codex_protocol::approvals::NetworkPolicyRuleAction;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::Event;
|
||||
use codex_protocol::protocol::EventMsg;
|
||||
use codex_protocol::protocol::ReviewDecision;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
use codex_protocol::protocol::WarningEvent;
|
||||
use indexmap::IndexMap;
|
||||
use std::collections::HashMap;
|
||||
@@ -127,11 +127,8 @@ fn allows_network_approval_flow(policy: AskForApproval) -> bool {
|
||||
!matches!(policy, AskForApproval::Never)
|
||||
}
|
||||
|
||||
fn sandbox_policy_allows_network_approval_flow(policy: &SandboxPolicy) -> bool {
|
||||
matches!(
|
||||
policy,
|
||||
SandboxPolicy::ReadOnly { .. } | SandboxPolicy::WorkspaceWrite { .. }
|
||||
)
|
||||
fn permission_profile_allows_network_approval_flow(permission_profile: &PermissionProfile) -> bool {
|
||||
matches!(permission_profile, PermissionProfile::Managed { .. })
|
||||
}
|
||||
|
||||
impl PendingApprovalDecision {
|
||||
@@ -359,8 +356,7 @@ impl NetworkApprovalService {
|
||||
.await;
|
||||
return NetworkDecision::deny(REASON_NOT_ALLOWED);
|
||||
};
|
||||
let sandbox_policy = turn_context.sandbox_policy();
|
||||
if !sandbox_policy_allows_network_approval_flow(&sandbox_policy) {
|
||||
if !permission_profile_allows_network_approval_flow(&turn_context.permission_profile()) {
|
||||
pending.set_decision(PendingApprovalDecision::Deny).await;
|
||||
self.pending_host_approvals.lock().await.remove(&key);
|
||||
self.record_outcome_for_single_active_call(NetworkApprovalOutcome::DeniedByPolicy(
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use super::*;
|
||||
use crate::sandboxing::SandboxPermissions;
|
||||
use codex_network_proxy::BlockedRequestArgs;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::permissions::NetworkSandboxPolicy;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
use core_test_support::PathBufExt;
|
||||
@@ -185,14 +187,19 @@ fn only_never_policy_disables_network_approval_flow() {
|
||||
|
||||
#[test]
|
||||
fn network_approval_flow_is_limited_to_restricted_sandbox_modes() {
|
||||
assert!(sandbox_policy_allows_network_approval_flow(
|
||||
&SandboxPolicy::new_read_only_policy()
|
||||
assert!(permission_profile_allows_network_approval_flow(
|
||||
&PermissionProfile::from_legacy_sandbox_policy(&SandboxPolicy::new_read_only_policy())
|
||||
));
|
||||
assert!(sandbox_policy_allows_network_approval_flow(
|
||||
&SandboxPolicy::new_workspace_write_policy()
|
||||
assert!(permission_profile_allows_network_approval_flow(
|
||||
&PermissionProfile::from_legacy_sandbox_policy(&SandboxPolicy::new_workspace_write_policy())
|
||||
));
|
||||
assert!(!sandbox_policy_allows_network_approval_flow(
|
||||
&SandboxPolicy::DangerFullAccess
|
||||
assert!(!permission_profile_allows_network_approval_flow(
|
||||
&PermissionProfile::Disabled
|
||||
));
|
||||
assert!(!permission_profile_allows_network_approval_flow(
|
||||
&PermissionProfile::External {
|
||||
network: NetworkSandboxPolicy::Restricted,
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user