permissions: centralize legacy sandbox projection (#19734)

## Why

The remaining migration work still needs `SandboxPolicy` at a few
compatibility boundaries, but those projections should come from one
canonical path. Keeping ad hoc legacy projections scattered through
app-server, CLI, and config code makes it easy for behavior to drift as
`PermissionProfile` gains fidelity that the legacy enum cannot
represent.

## What Changed

- Adds `Permissions::legacy_sandbox_policy(cwd)` and
`Config::legacy_sandbox_policy()` as the compatibility projection from
the canonical `PermissionProfile`.
- Adds `Permissions::can_set_legacy_sandbox_policy()` so legacy inputs
are checked after they are converted into profile semantics.
- Updates app-server command handling, Windows sandbox setup, session
configuration, and sandbox summaries to use the centralized projection
helper.
- Leaves `SandboxPolicy` in place only for boundary inputs/outputs that
still speak the legacy abstraction.

## Verification

- `cargo check -p codex-config -p codex-core -p codex-sandboxing -p
codex-app-server -p codex-cli -p codex-tui`
- `cargo test -p codex-tui
permissions_selection_history_snapshot_full_access_to_default --
--nocapture`
- `cargo test -p codex-tui
permissions_selection_sends_approvals_reviewer_in_override_turn_context
-- --nocapture`
- `bazel test //codex-rs/tui:tui-unit-tests-bin
--test_arg=permissions_selection_history_snapshot_full_access_to_default
--test_output=errors`
- `bazel test //codex-rs/tui:tui-unit-tests-bin
--test_arg=permissions_selection_sends_approvals_reviewer_in_override_turn_context
--test_output=errors`


---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/19734).
* #19737
* #19736
* #19735
* __->__ #19734
This commit is contained in:
Michael Bolin
2026-04-26 20:31:23 -07:00
committed by GitHub
Unverified
parent c3e60849e5
commit 0d8cdc0510
16 changed files with 210 additions and 86 deletions
@@ -2307,7 +2307,11 @@ impl CodexMessageProcessor {
}
}
} else if let Some(policy) = sandbox_policy.map(|policy| policy.to_core()) {
match self.config.permissions.sandbox_policy.can_set(&policy) {
match self
.config
.permissions
.can_set_legacy_sandbox_policy(&policy, &sandbox_cwd)
{
Ok(()) => {
let file_system_sandbox_policy =
codex_protocol::permissions::FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(&policy, &sandbox_cwd);
@@ -8705,7 +8709,9 @@ impl CodexMessageProcessor {
Ok(config) => {
let setup_request = WindowsSandboxSetupRequest {
mode,
policy: config.permissions.sandbox_policy.get().clone(),
policy: config
.permissions
.legacy_sandbox_policy(config.cwd.as_path()),
policy_cwd: config.cwd.to_path_buf(),
command_cwd,
env_map: std::env::vars().collect(),
+7 -2
View File
@@ -227,7 +227,9 @@ async fn run_command_under_sandbox(
let args = create_linux_sandbox_command_args_for_policies(
command,
cwd.as_path(),
config.permissions.sandbox_policy.get(),
&config
.permissions
.legacy_sandbox_policy(sandbox_policy_cwd.as_path()),
&file_system_sandbox_policy,
network_sandbox_policy,
sandbox_policy_cwd.as_path(),
@@ -290,7 +292,10 @@ async fn run_command_under_windows_session(
use codex_windows_sandbox::spawn_windows_sandbox_session_elevated;
use codex_windows_sandbox::spawn_windows_sandbox_session_legacy;
let policy_str = match serde_json::to_string(config.permissions.sandbox_policy.get()) {
let sandbox_policy = config
.permissions
.legacy_sandbox_policy(sandbox_policy_cwd.as_path());
let policy_str = match serde_json::to_string(&sandbox_policy) {
Ok(policy_str) => policy_str,
Err(err) => {
eprintln!("windows sandbox failed to serialize policy: {err}");
+32 -2
View File
@@ -237,6 +237,37 @@ impl Permissions {
self.permission_profile.get().network_sandbox_policy()
}
/// Legacy compatibility projection derived from the canonical profile.
pub fn legacy_sandbox_policy(&self, cwd: &Path) -> SandboxPolicy {
let permission_profile = self.permission_profile.get();
let file_system_sandbox_policy = permission_profile.file_system_sandbox_policy();
compatibility_sandbox_policy_for_permission_profile(
permission_profile,
&file_system_sandbox_policy,
permission_profile.network_sandbox_policy(),
cwd,
)
}
/// Check whether a legacy sandbox policy can be applied to this permission
/// set under both legacy and canonical profile constraints.
pub fn can_set_legacy_sandbox_policy(
&self,
sandbox_policy: &SandboxPolicy,
cwd: &Path,
) -> ConstraintResult<()> {
self.sandbox_policy.can_set(sandbox_policy)?;
let file_system_sandbox_policy =
FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(sandbox_policy, cwd);
let network_sandbox_policy = NetworkSandboxPolicy::from(sandbox_policy);
let permission_profile = PermissionProfile::from_runtime_permissions_with_enforcement(
SandboxEnforcement::from_legacy_sandbox_policy(sandbox_policy),
&file_system_sandbox_policy,
network_sandbox_policy,
);
self.permission_profile.can_set(&permission_profile)
}
/// Replace permissions from a legacy sandbox policy and keep every
/// permission projection in sync.
pub fn set_legacy_sandbox_policy(
@@ -244,7 +275,7 @@ impl Permissions {
sandbox_policy: SandboxPolicy,
cwd: &Path,
) -> ConstraintResult<()> {
self.sandbox_policy.can_set(&sandbox_policy)?;
self.can_set_legacy_sandbox_policy(&sandbox_policy, cwd)?;
let file_system_sandbox_policy =
FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(&sandbox_policy, cwd);
let network_sandbox_policy = NetworkSandboxPolicy::from(&sandbox_policy);
@@ -253,7 +284,6 @@ impl Permissions {
&file_system_sandbox_policy,
network_sandbox_policy,
);
self.permission_profile.can_set(&permission_profile)?;
self.sandbox_policy.set(sandbox_policy)?;
self.permission_profile.set(permission_profile)?;
+3 -1
View File
@@ -634,7 +634,9 @@ impl Session {
config.model_context_window,
config.model_auto_compact_token_limit,
config.permissions.approval_policy.value(),
config.permissions.sandbox_policy.get().clone(),
config
.permissions
.legacy_sandbox_policy(session_configuration.cwd.as_path()),
mcp_servers.keys().map(String::as_str).collect(),
config.active_profile.clone(),
);
+6 -2
View File
@@ -939,10 +939,14 @@ impl App {
// On startup, if Agent mode (workspace-write) or ReadOnly is active, warn about world-writable dirs on Windows.
#[cfg(target_os = "windows")]
{
let startup_sandbox_policy = app
.config
.permissions
.legacy_sandbox_policy(app.config.cwd.as_path());
let should_check = WindowsSandboxLevel::from_config(&app.config)
!= WindowsSandboxLevel::Disabled
&& matches!(
app.config.permissions.sandbox_policy.get(),
&startup_sandbox_policy,
codex_protocol::protocol::SandboxPolicy::WorkspaceWrite { .. }
| codex_protocol::protocol::SandboxPolicy::ReadOnly { .. }
)
@@ -956,7 +960,7 @@ impl App {
let env_map: std::collections::HashMap<String, String> = std::env::vars().collect();
let tx = app.app_event_tx.clone();
let logs_base_dir = app.config.codex_home.clone();
let sandbox_policy = app.config.permissions.sandbox_policy.get().clone();
let sandbox_policy = startup_sandbox_policy;
Self::spawn_world_writable_scan(cwd, env_map, logs_base_dir, sandbox_policy, tx);
}
}
+10 -5
View File
@@ -300,9 +300,11 @@ impl App {
.set_approval_policy(self.config.permissions.approval_policy.value());
}
if sandbox_policy_override.is_some()
&& let Err(err) = self
.chat_widget
.set_sandbox_policy(self.config.permissions.sandbox_policy.get().clone())
&& let Err(err) = self.chat_widget.set_sandbox_policy(
self.config
.permissions
.legacy_sandbox_policy(self.config.cwd.as_path()),
)
{
tracing::error!(
error = %err,
@@ -312,8 +314,11 @@ impl App {
.add_error_message(format!("Failed to enable Auto-review: {err}"));
}
if sandbox_policy_override.is_some() {
self.runtime_sandbox_policy_override =
Some(self.config.permissions.sandbox_policy.get().clone());
self.runtime_sandbox_policy_override = Some(
self.config
.permissions
.legacy_sandbox_policy(self.config.cwd.as_path()),
);
}
if approval_policy_override.is_some()
+13 -4
View File
@@ -834,7 +834,10 @@ impl App {
/*hint*/ None,
));
let policy = self.config.permissions.sandbox_policy.get().clone();
let policy = self
.config
.permissions
.legacy_sandbox_policy(self.config.cwd.as_path());
let policy_cwd = self.config.cwd.clone();
let command_cwd = self.config.cwd.clone();
let env_map: std::collections::HashMap<String, String> =
@@ -1245,8 +1248,11 @@ impl App {
.add_error_message(format!("Failed to set sandbox policy: {err}"));
return Ok(AppRunControl::Continue);
}
self.runtime_sandbox_policy_override =
Some(self.config.permissions.sandbox_policy.get().clone());
self.runtime_sandbox_policy_override = Some(
self.config
.permissions
.legacy_sandbox_policy(self.config.cwd.as_path()),
);
self.sync_active_thread_permission_settings_to_cached_session()
.await;
@@ -1269,7 +1275,10 @@ impl App {
std::env::vars().collect();
let tx = self.app_event_tx.clone();
let logs_base_dir = self.config.codex_home.clone();
let sandbox_policy = self.config.permissions.sandbox_policy.get().clone();
let sandbox_policy = self
.config
.permissions
.legacy_sandbox_policy(self.config.cwd.as_path());
Self::spawn_world_writable_scan(
cwd,
env_map,
+12 -4
View File
@@ -12,7 +12,10 @@ impl App {
let approval_policy = self.config.permissions.approval_policy.value();
let approvals_reviewer = self.config.approvals_reviewer;
let sandbox_policy = self.config.permissions.sandbox_policy.get().clone();
let sandbox_policy = self
.config
.permissions
.legacy_sandbox_policy(self.config.cwd.as_path());
let permission_profile = Some(
self.chat_widget
.config_ref()
@@ -45,7 +48,10 @@ impl App {
thread_id: ThreadId,
thread: &Thread,
) -> ThreadSessionState {
let sandbox_policy = self.config.permissions.sandbox_policy.get().clone();
let sandbox_policy = self
.config
.permissions
.legacy_sandbox_policy(self.config.cwd.as_path());
let mut session = self
.primary_session_configured
.clone()
@@ -185,8 +191,10 @@ mod tests {
app.chat_widget
.set_sandbox_policy(expected_sandbox_policy.clone())
.expect("set widget sandbox policy");
app.config.permissions.sandbox_policy =
codex_config::Constrained::allow_any(expected_sandbox_policy.clone());
app.config
.permissions
.set_legacy_sandbox_policy(expected_sandbox_policy.clone(), app.config.cwd.as_path())
.expect("set app sandbox policy");
app.sync_active_thread_permission_settings_to_cached_session()
.await;
+31 -7
View File
@@ -1143,7 +1143,13 @@ fn thread_start_params_from_config(
let permission_profile = permission_profile_override_from_config(config, thread_params_mode);
let sandbox = permission_profile
.is_none()
.then(|| sandbox_mode_from_policy(config.permissions.sandbox_policy.get().clone()))
.then(|| {
sandbox_mode_from_policy(
config
.permissions
.legacy_sandbox_policy(config.cwd.as_path()),
)
})
.flatten();
ThreadStartParams {
model: config.model.clone(),
@@ -1170,7 +1176,13 @@ fn thread_resume_params_from_config(
let permission_profile = permission_profile_override_from_config(&config, thread_params_mode);
let sandbox = permission_profile
.is_none()
.then(|| sandbox_mode_from_policy(config.permissions.sandbox_policy.get().clone()))
.then(|| {
sandbox_mode_from_policy(
config
.permissions
.legacy_sandbox_policy(config.cwd.as_path()),
)
})
.flatten();
ThreadResumeParams {
thread_id: thread_id.to_string(),
@@ -1196,7 +1208,13 @@ fn thread_fork_params_from_config(
let permission_profile = permission_profile_override_from_config(&config, thread_params_mode);
let sandbox = permission_profile
.is_none()
.then(|| sandbox_mode_from_policy(config.permissions.sandbox_policy.get().clone()))
.then(|| {
sandbox_mode_from_policy(
config
.permissions
.legacy_sandbox_policy(config.cwd.as_path()),
)
})
.flatten();
ThreadForkParams {
thread_id: thread_id.to_string(),
@@ -1522,8 +1540,11 @@ mod tests {
let temp_dir = tempfile::tempdir().expect("tempdir");
let config = build_config(&temp_dir).await;
let thread_id = ThreadId::new();
let expected_sandbox =
sandbox_mode_from_policy(config.permissions.sandbox_policy.get().clone());
let expected_sandbox = sandbox_mode_from_policy(
config
.permissions
.legacy_sandbox_policy(config.cwd.as_path()),
);
let start = thread_start_params_from_config(
&config,
@@ -1564,8 +1585,11 @@ mod tests {
let config = build_config(&temp_dir).await;
let thread_id = ThreadId::new();
let remote_cwd = PathBuf::from("repo/on/server");
let expected_sandbox =
sandbox_mode_from_policy(config.permissions.sandbox_policy.get().clone());
let expected_sandbox = sandbox_mode_from_policy(
config
.permissions
.legacy_sandbox_policy(config.cwd.as_path()),
);
let start = thread_start_params_from_config(
&config,
+26 -7
View File
@@ -6415,7 +6415,9 @@ impl ChatWidget {
items,
self.config.cwd.to_path_buf(),
self.config.permissions.approval_policy.value(),
self.config.permissions.sandbox_policy.get().clone(),
self.config
.permissions
.legacy_sandbox_policy(self.config.cwd.as_path()),
permission_profile,
effective_mode.model().to_string(),
effective_mode.reasoning_effort(),
@@ -9466,7 +9468,10 @@ impl ChatWidget {
pub(crate) fn open_permissions_popup(&mut self) {
let include_read_only = cfg!(target_os = "windows");
let current_approval = self.config.permissions.approval_policy.value();
let current_sandbox = self.config.permissions.sandbox_policy.get();
let current_sandbox = self
.config
.permissions
.legacy_sandbox_policy(self.config.cwd.as_path());
let guardian_approval_enabled = self.config.features.enabled(Feature::GuardianApproval);
let current_review_policy = self.config.approvals_reviewer;
let mut items: Vec<SelectionItem> = Vec::new();
@@ -9600,7 +9605,11 @@ impl ChatWidget {
name: base_name.clone(),
description: base_description.clone(),
is_current: current_review_policy == ApprovalsReviewer::User
&& Self::preset_matches_current(current_approval, current_sandbox, &preset),
&& Self::preset_matches_current(
current_approval,
&current_sandbox,
&preset,
),
actions: default_actions,
dismiss_on_select: true,
disabled_reason: default_disabled_reason,
@@ -9617,7 +9626,7 @@ impl ChatWidget {
is_current: current_review_policy == ApprovalsReviewer::AutoReview
&& Self::preset_matches_current(
current_approval,
current_sandbox,
&current_sandbox,
&preset,
),
actions: Self::approval_preset_actions(
@@ -9638,7 +9647,7 @@ impl ChatWidget {
description: base_description,
is_current: Self::preset_matches_current(
current_approval,
current_sandbox,
&current_sandbox,
&preset,
),
actions: default_actions,
@@ -9774,7 +9783,10 @@ impl ChatWidget {
self.config.codex_home.as_path(),
cwd.as_path(),
&env_map,
self.config.permissions.sandbox_policy.get(),
&self
.config
.permissions
.legacy_sandbox_policy(self.config.cwd.as_path()),
Some(self.config.codex_home.as_path()),
) {
Ok(_) => None,
@@ -9892,7 +9904,14 @@ impl ChatWidget {
let mode_label = preset
.as_ref()
.map(|p| describe_policy(&p.sandbox))
.unwrap_or_else(|| describe_policy(self.config.permissions.sandbox_policy.get()));
.unwrap_or_else(|| {
describe_policy(
&self
.config
.permissions
.legacy_sandbox_policy(self.config.cwd.as_path()),
)
});
let info_line = if failed_scan {
Line::from(vec![
"We couldn't complete the world-writable scan, so protections cannot be verified. "
@@ -1,6 +1,13 @@
use super::*;
use pretty_assertions::assert_eq;
fn set_legacy_sandbox_policy(chat: &mut ChatWidget, sandbox_policy: SandboxPolicy) {
chat.config
.permissions
.set_legacy_sandbox_policy(sandbox_policy, chat.config.cwd.as_path())
.expect("set sandbox policy");
}
#[tokio::test]
async fn approvals_selection_popup_snapshot() {
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
@@ -347,8 +354,7 @@ async fn permissions_selection_history_snapshot_full_access_to_default() {
.approval_policy
.set(AskForApproval::Never)
.expect("set approval policy");
chat.config.permissions.sandbox_policy =
Constrained::allow_any(SandboxPolicy::DangerFullAccess);
set_legacy_sandbox_policy(&mut chat, SandboxPolicy::DangerFullAccess);
chat.open_permissions_popup();
let popup = render_bottom_popup(&chat, /*width*/ 120);
@@ -387,11 +393,7 @@ async fn permissions_selection_emits_history_cell_when_current_is_selected() {
.approval_policy
.set(AskForApproval::OnRequest)
.expect("set approval policy");
chat.config
.permissions
.sandbox_policy
.set(SandboxPolicy::new_workspace_write_policy())
.expect("set sandbox policy");
set_legacy_sandbox_policy(&mut chat, SandboxPolicy::new_workspace_write_policy());
chat.open_permissions_popup();
chat.handle_key_event(KeyEvent::from(KeyCode::Enter));
@@ -446,11 +448,7 @@ async fn permissions_selection_hides_auto_review_when_feature_disabled_even_if_a
.approval_policy
.set(AskForApproval::OnRequest)
.expect("set approval policy");
chat.config
.permissions
.sandbox_policy
.set(SandboxPolicy::new_workspace_write_policy())
.expect("set sandbox policy");
set_legacy_sandbox_policy(&mut chat, SandboxPolicy::new_workspace_write_policy());
chat.open_permissions_popup();
let popup = render_bottom_popup(&chat, /*width*/ 120);
@@ -575,11 +573,7 @@ async fn permissions_selection_can_disable_auto_review() {
.approval_policy
.set(AskForApproval::OnRequest)
.expect("set approval policy");
chat.config
.permissions
.sandbox_policy
.set(SandboxPolicy::new_workspace_write_policy())
.expect("set sandbox policy");
set_legacy_sandbox_policy(&mut chat, SandboxPolicy::new_workspace_write_policy());
chat.open_permissions_popup();
chat.handle_key_event(KeyEvent::from(KeyCode::Up));
@@ -616,11 +610,7 @@ async fn permissions_selection_sends_approvals_reviewer_in_override_turn_context
.approval_policy
.set(AskForApproval::OnRequest)
.expect("set approval policy");
chat.config
.permissions
.sandbox_policy
.set(SandboxPolicy::new_workspace_write_policy())
.expect("set sandbox policy");
set_legacy_sandbox_policy(&mut chat, SandboxPolicy::new_workspace_write_policy());
chat.set_approvals_reviewer(ApprovalsReviewer::User);
chat.open_permissions_popup();
+3 -1
View File
@@ -1313,7 +1313,9 @@ pub(crate) fn new_session_info(
pub(crate) fn is_yolo_mode(config: &Config) -> bool {
has_yolo_permissions(
config.permissions.approval_policy.value(),
config.permissions.sandbox_policy.get(),
&config
.permissions
.legacy_sandbox_policy(config.cwd.as_path()),
)
}
+11 -4
View File
@@ -874,9 +874,12 @@ pub async fn run_main(
set_default_client_residency_requirement(config.enforce_residency.value());
if let Some(warning) =
add_dir_warning_message(&cli.add_dir, config.permissions.sandbox_policy.get())
{
if let Some(warning) = add_dir_warning_message(
&cli.add_dir,
&config
.permissions
.legacy_sandbox_policy(config.cwd.as_path()),
) {
#[allow(clippy::print_stderr)]
{
eprintln!("Error adding directories: {warning}");
@@ -2205,7 +2208,9 @@ mod tests {
current_date: None,
timezone: None,
approval_policy: config.permissions.approval_policy.value(),
sandbox_policy: config.permissions.sandbox_policy.get().clone(),
sandbox_policy: config
.permissions
.legacy_sandbox_policy(config.cwd.as_path()),
permission_profile: None,
network: None,
file_system_sandbox_policy: None,
@@ -2328,6 +2333,7 @@ trust_level = "untrusted"
..Default::default()
};
let trusted_config = ConfigBuilder::default()
.loader_overrides(LoaderOverrides::without_managed_config_for_tests())
.codex_home(codex_home.clone())
.harness_overrides(trusted_overrides.clone())
.build()
@@ -2342,6 +2348,7 @@ trust_level = "untrusted"
..trusted_overrides
};
let untrusted_config = ConfigBuilder::default()
.loader_overrides(LoaderOverrides::without_managed_config_for_tests())
.codex_home(codex_home)
.harness_overrides(untrusted_overrides)
.build()
+11 -5
View File
@@ -254,7 +254,11 @@ impl StatusHistoryCell {
),
(
"sandbox",
summarize_sandbox_policy(config.permissions.sandbox_policy.get()),
summarize_sandbox_policy(
&config
.permissions
.legacy_sandbox_policy(config.cwd.as_path()),
),
),
];
if config.model_provider.wire_api == WireApi::Responses {
@@ -277,7 +281,10 @@ impl StatusHistoryCell {
.find(|(k, _)| *k == "approval")
.map(|(_, v)| v.clone())
.unwrap_or_else(|| "<unknown>".to_string());
let sandbox = match config.permissions.sandbox_policy.get() {
let sandbox_policy = config
.permissions
.legacy_sandbox_policy(config.cwd.as_path());
let sandbox = match &sandbox_policy {
SandboxPolicy::DangerFullAccess => "danger-full-access".to_string(),
SandboxPolicy::ReadOnly { .. } => "read-only".to_string(),
SandboxPolicy::WorkspaceWrite {
@@ -294,12 +301,11 @@ impl StatusHistoryCell {
}
};
let permissions = if config.permissions.approval_policy.value() == AskForApproval::OnRequest
&& *config.permissions.sandbox_policy.get()
== SandboxPolicy::new_workspace_write_policy()
&& sandbox_policy == SandboxPolicy::new_workspace_write_policy()
{
"Default".to_string()
} else if config.permissions.approval_policy.value() == AskForApproval::Never
&& *config.permissions.sandbox_policy.get() == SandboxPolicy::DangerFullAccess
&& sandbox_policy == SandboxPolicy::DangerFullAccess
{
"Full Access".to_string()
} else {
+20 -17
View File
@@ -97,19 +97,20 @@ async fn status_snapshot_includes_reasoning_details() {
config.model = Some("gpt-5.1-codex-max".to_string());
config.model_provider_id = "openai".to_string();
config.model_reasoning_summary = Some(ReasoningSummary::Detailed);
config.cwd = test_path_buf("/workspace/tests").abs();
config
.permissions
.sandbox_policy
.set(SandboxPolicy::WorkspaceWrite {
writable_roots: Vec::new(),
network_access: false,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
})
.set_legacy_sandbox_policy(
SandboxPolicy::WorkspaceWrite {
writable_roots: Vec::new(),
network_access: false,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
},
config.cwd.as_path(),
)
.expect("set sandbox policy");
config.cwd = test_path_buf("/workspace/tests").abs();
let account_display = test_status_account_display();
let usage = TokenUsage {
input_tokens: 1_200,
@@ -182,17 +183,19 @@ async fn status_permissions_non_default_workspace_write_is_custom() {
.approval_policy
.set(AskForApproval::OnRequest)
.expect("set approval policy");
config.cwd = test_path_buf("/workspace/tests").abs();
config
.permissions
.sandbox_policy
.set(SandboxPolicy::WorkspaceWrite {
writable_roots: Vec::new(),
network_access: true,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
})
.set_legacy_sandbox_policy(
SandboxPolicy::WorkspaceWrite {
writable_roots: Vec::new(),
network_access: true,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
},
config.cwd.as_path(),
)
.expect("set sandbox policy");
config.cwd = test_path_buf("/workspace/tests").abs();
let account_display = test_status_account_display();
let usage = TokenUsage::default();
@@ -15,7 +15,11 @@ pub fn create_config_summary_entries(config: &Config, model: &str) -> Vec<(&'sta
),
(
"sandbox",
summarize_sandbox_policy(config.permissions.sandbox_policy.get()),
summarize_sandbox_policy(
&config
.permissions
.legacy_sandbox_policy(config.cwd.as_path()),
),
),
];
if config.model_provider.wire_api == WireApi::Responses {