Skip to content

Commit c2b1d35

Browse files
committed
permissions: derive snapshot sandbox projections
1 parent bbec1f1 commit c2b1d35

5 files changed

Lines changed: 26 additions & 16 deletions

File tree

codex-rs/app-server/src/codex_message_processor.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2729,6 +2729,7 @@ impl CodexMessageProcessor {
27292729
/*has_in_progress_turn*/ false,
27302730
);
27312731

2732+
let sandbox_policy = config_snapshot.sandbox_policy();
27322733
let permission_profile =
27332734
thread_response_permission_profile(config_snapshot.permission_profile);
27342735

@@ -2741,7 +2742,7 @@ impl CodexMessageProcessor {
27412742
instruction_sources,
27422743
approval_policy: config_snapshot.approval_policy.into(),
27432744
approvals_reviewer: config_snapshot.approvals_reviewer.into(),
2744-
sandbox: config_snapshot.sandbox_policy.into(),
2745+
sandbox: sandbox_policy.into(),
27452746
permission_profile,
27462747
reasoning_effort: config_snapshot.reasoning_effort,
27472748
};
@@ -3465,7 +3466,7 @@ impl CodexMessageProcessor {
34653466
builder.model_provider = Some(model_provider.clone());
34663467
builder.cwd = config_snapshot.cwd.to_path_buf();
34673468
builder.cli_version = Some(env!("CARGO_PKG_VERSION").to_string());
3468-
builder.sandbox_policy = config_snapshot.sandbox_policy.clone();
3469+
builder.sandbox_policy = config_snapshot.sandbox_policy();
34693470
builder.approval_mode = config_snapshot.approval_policy;
34703471
let metadata = builder.build(model_provider.as_str());
34713472
if let Err(err) = state_db_ctx.insert_thread_if_absent(&metadata).await {
@@ -4555,7 +4556,7 @@ impl CodexMessageProcessor {
45554556
instruction_sources,
45564557
approval_policy: session_configured.approval_policy.into(),
45574558
approvals_reviewer: session_configured.approvals_reviewer.into(),
4558-
sandbox: config_snapshot.sandbox_policy.into(),
4559+
sandbox: config_snapshot.sandbox_policy().into(),
45594560
permission_profile,
45604561
reasoning_effort: session_configured.reasoning_effort,
45614562
};
@@ -5284,7 +5285,7 @@ impl CodexMessageProcessor {
52845285
instruction_sources,
52855286
approval_policy: session_configured.approval_policy.into(),
52865287
approvals_reviewer: session_configured.approvals_reviewer.into(),
5287-
sandbox: config_snapshot.sandbox_policy.into(),
5288+
sandbox: config_snapshot.sandbox_policy().into(),
52885289
permission_profile,
52895290
reasoning_effort: session_configured.reasoning_effort,
52905291
};
@@ -8756,13 +8757,13 @@ async fn handle_pending_thread_resume_request(
87568757
tracing::warn!("failed to apply goal resume runtime effects: {err}");
87578758
}
87588759

8760+
let sandbox_policy = pending.config_snapshot.sandbox_policy();
87598761
let ThreadConfigSnapshot {
87608762
model,
87618763
model_provider_id,
87628764
service_tier,
87638765
approval_policy,
87648766
approvals_reviewer,
8765-
sandbox_policy,
87668767
permission_profile,
87678768
cwd,
87688769
reasoning_effort,
@@ -8985,8 +8986,9 @@ fn collect_resume_override_mismatches(
89858986
}
89868987
}
89878988
if let Some(requested_sandbox) = request.sandbox.as_ref() {
8989+
let active_sandbox = config_snapshot.sandbox_policy();
89888990
let sandbox_matches = matches!(
8989-
(requested_sandbox, &config_snapshot.sandbox_policy),
8991+
(requested_sandbox, &active_sandbox),
89908992
(
89918993
SandboxMode::ReadOnly,
89928994
codex_protocol::protocol::SandboxPolicy::ReadOnly { .. }
@@ -9003,8 +9005,7 @@ fn collect_resume_override_mismatches(
90039005
);
90049006
if !sandbox_matches {
90059007
mismatch_details.push(format!(
9006-
"sandbox requested={requested_sandbox:?} active={:?}",
9007-
config_snapshot.sandbox_policy
9008+
"sandbox requested={requested_sandbox:?} active={active_sandbox:?}"
90089009
));
90099010
}
90109011
}
@@ -10690,7 +10691,6 @@ mod tests {
1069010691
service_tier: Some(codex_protocol::config_types::ServiceTier::Flex),
1069110692
approval_policy: codex_protocol::protocol::AskForApproval::OnRequest,
1069210693
approvals_reviewer: codex_protocol::config_types::ApprovalsReviewer::User,
10693-
sandbox_policy: codex_protocol::protocol::SandboxPolicy::DangerFullAccess,
1069410694
permission_profile: codex_protocol::models::PermissionProfile::Disabled,
1069510695
cwd,
1069610696
ephemeral: false,

codex-rs/core/src/codex_thread.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ pub struct ThreadConfigSnapshot {
4747
pub service_tier: Option<ServiceTier>,
4848
pub approval_policy: AskForApproval,
4949
pub approvals_reviewer: ApprovalsReviewer,
50-
pub sandbox_policy: SandboxPolicy,
5150
pub permission_profile: PermissionProfile,
5251
pub cwd: AbsolutePathBuf,
5352
pub ephemeral: bool,
@@ -56,6 +55,18 @@ pub struct ThreadConfigSnapshot {
5655
pub session_source: SessionSource,
5756
}
5857

58+
impl ThreadConfigSnapshot {
59+
pub fn sandbox_policy(&self) -> SandboxPolicy {
60+
let file_system_sandbox_policy = self.permission_profile.file_system_sandbox_policy();
61+
codex_sandboxing::compatibility_sandbox_policy_for_permission_profile(
62+
&self.permission_profile,
63+
&file_system_sandbox_policy,
64+
self.permission_profile.network_sandbox_policy(),
65+
self.cwd.as_path(),
66+
)
67+
}
68+
}
69+
5970
/// Turn context overrides that app-server validates before starting a turn.
6071
#[derive(Clone, Default)]
6172
pub struct CodexThreadTurnContextOverrides {

codex-rs/core/src/memories/tests.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -883,11 +883,11 @@ mod phase2 {
883883
config_snapshot.cwd.as_path(),
884884
memory_root(&harness.config.codex_home).as_path()
885885
);
886-
match &config_snapshot.sandbox_policy {
886+
let sandbox_policy = config_snapshot.sandbox_policy();
887+
match &sandbox_policy {
887888
SandboxPolicy::WorkspaceWrite { network_access, .. } => {
888889
assert!(!*network_access);
889-
let effective_writable_roots: Vec<_> = config_snapshot
890-
.sandbox_policy
890+
let effective_writable_roots: Vec<_> = sandbox_policy
891891
.get_writable_roots_with_cwd(config_snapshot.cwd.as_path())
892892
.into_iter()
893893
.map(|root| root.root)
@@ -917,7 +917,7 @@ mod phase2 {
917917
let file_system_sandbox_policy = turn_context.file_system_sandbox_policy();
918918
let legacy_file_system_sandbox_policy =
919919
FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(
920-
&config_snapshot.sandbox_policy,
920+
&sandbox_policy,
921921
config_snapshot.cwd.as_path(),
922922
);
923923
assert!(

codex-rs/core/src/session/session.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ impl SessionConfiguration {
126126
service_tier: self.service_tier,
127127
approval_policy: self.approval_policy.value(),
128128
approvals_reviewer: self.approvals_reviewer,
129-
sandbox_policy: self.sandbox_policy(),
130129
permission_profile: self.permission_profile(),
131130
cwd: self.cwd.clone(),
132131
ephemeral: self.original_config_do_not_use.ephemeral,

codex-rs/core/src/tools/handlers/multi_agents_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2143,7 +2143,7 @@ async fn spawn_agent_reapplies_runtime_sandbox_after_role_config() {
21432143
.expect("spawned agent thread should exist")
21442144
.config_snapshot()
21452145
.await;
2146-
assert_eq!(snapshot.sandbox_policy, expected_sandbox);
2146+
assert_eq!(snapshot.sandbox_policy(), expected_sandbox);
21472147
assert_eq!(snapshot.approval_policy, AskForApproval::OnRequest);
21482148
assert_eq!(snapshot.permission_profile, expected_permission_profile);
21492149
let child_thread = manager

0 commit comments

Comments
 (0)