Skip to content

Commit 0b51e47

Browse files
committed
permissions: derive config defaults as profiles
1 parent 4b55979 commit 0b51e47

6 files changed

Lines changed: 542 additions & 317 deletions

File tree

codex-rs/config/src/config_toml.rs

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ use codex_protocol::config_types::WebSearchToolConfig;
4949
use codex_protocol::config_types::WindowsSandboxLevel;
5050
use codex_protocol::models::PermissionProfile;
5151
use codex_protocol::openai_models::ReasoningEffort;
52+
use codex_protocol::permissions::NetworkSandboxPolicy;
5253
use codex_protocol::protocol::AskForApproval;
53-
use codex_protocol::protocol::SandboxPolicy;
5454
use codex_utils_absolute_path::AbsolutePathBuf;
5555
use codex_utils_path::normalize_for_path_comparison;
5656
use schemars::JsonSchema;
@@ -641,15 +641,19 @@ pub struct GhostSnapshotToml {
641641
}
642642

643643
impl ConfigToml {
644-
/// Derive the effective sandbox policy from the configuration.
645-
pub async fn derive_sandbox_policy(
644+
/// Derive the effective permission profile from legacy sandbox config.
645+
///
646+
/// Call this only after ruling out `default_permissions`: named
647+
/// `[permissions]` profiles must be compiled through the permissions
648+
/// profile pipeline, not reconstructed from `sandbox_mode`.
649+
pub async fn derive_permission_profile(
646650
&self,
647651
sandbox_mode_override: Option<SandboxMode>,
648652
profile_sandbox_mode: Option<SandboxMode>,
649653
windows_sandbox_level: WindowsSandboxLevel,
650654
active_project: Option<&ProjectConfig>,
651655
permission_profile_constraint: Option<&crate::Constrained<PermissionProfile>>,
652-
) -> SandboxPolicy {
656+
) -> PermissionProfile {
653657
let sandbox_mode_was_explicit = sandbox_mode_override.is_some()
654658
|| profile_sandbox_mode.is_some()
655659
|| self.sandbox_mode.is_some();
@@ -677,50 +681,53 @@ impl ConfigToml {
677681
})
678682
})
679683
.unwrap_or_default();
680-
let mut sandbox_policy = match resolved_sandbox_mode {
681-
SandboxMode::ReadOnly => SandboxPolicy::new_read_only_policy(),
684+
let effective_sandbox_mode = if cfg!(target_os = "windows")
685+
// If the experimental Windows sandbox is enabled, do not force a downgrade.
686+
&& windows_sandbox_level == WindowsSandboxLevel::Disabled
687+
&& matches!(resolved_sandbox_mode, SandboxMode::WorkspaceWrite)
688+
{
689+
SandboxMode::ReadOnly
690+
} else {
691+
resolved_sandbox_mode
692+
};
693+
694+
let permission_profile = match effective_sandbox_mode {
695+
SandboxMode::ReadOnly => PermissionProfile::read_only(),
682696
SandboxMode::WorkspaceWrite => match self.sandbox_workspace_write.as_ref() {
683697
Some(SandboxWorkspaceWrite {
684698
writable_roots,
685699
network_access,
686700
exclude_tmpdir_env_var,
687701
exclude_slash_tmp,
688-
}) => SandboxPolicy::WorkspaceWrite {
689-
writable_roots: writable_roots.clone(),
690-
network_access: *network_access,
691-
exclude_tmpdir_env_var: *exclude_tmpdir_env_var,
692-
exclude_slash_tmp: *exclude_slash_tmp,
693-
},
694-
None => SandboxPolicy::new_workspace_write_policy(),
702+
}) => {
703+
let network_policy = if *network_access {
704+
NetworkSandboxPolicy::Enabled
705+
} else {
706+
NetworkSandboxPolicy::Restricted
707+
};
708+
PermissionProfile::workspace_write_with(
709+
writable_roots,
710+
network_policy,
711+
*exclude_tmpdir_env_var,
712+
*exclude_slash_tmp,
713+
)
714+
}
715+
None => PermissionProfile::workspace_write(),
695716
},
696-
SandboxMode::DangerFullAccess => SandboxPolicy::DangerFullAccess,
697-
};
698-
let downgrade_workspace_write_if_unsupported = |policy: &mut SandboxPolicy| {
699-
if cfg!(target_os = "windows")
700-
// If the experimental Windows sandbox is enabled, do not force a downgrade.
701-
&& windows_sandbox_level == WindowsSandboxLevel::Disabled
702-
&& matches!(&*policy, SandboxPolicy::WorkspaceWrite { .. })
703-
{
704-
*policy = SandboxPolicy::new_read_only_policy();
705-
}
717+
SandboxMode::DangerFullAccess => PermissionProfile::Disabled,
706718
};
707-
if matches!(resolved_sandbox_mode, SandboxMode::WorkspaceWrite) {
708-
downgrade_workspace_write_if_unsupported(&mut sandbox_policy);
709-
}
710719
if !sandbox_mode_was_explicit
711720
&& let Some(constraint) = permission_profile_constraint
712-
&& let Err(err) = constraint.can_set(&PermissionProfile::from_legacy_sandbox_policy(
713-
&sandbox_policy,
714-
))
721+
&& let Err(err) = constraint.can_set(&permission_profile)
715722
{
716723
tracing::warn!(
717724
error = %err,
718725
"default sandbox policy is disallowed by requirements; falling back to required default"
719726
);
720-
sandbox_policy = SandboxPolicy::new_read_only_policy();
721-
downgrade_workspace_write_if_unsupported(&mut sandbox_policy);
727+
PermissionProfile::read_only()
728+
} else {
729+
permission_profile
722730
}
723-
sandbox_policy
724731
}
725732

726733
/// Resolves the cwd to an existing project, or returns None if ConfigToml

0 commit comments

Comments
 (0)