mirror of
https://github.com/openai/codex.git
synced 2026-11-13 06:45:07 +00:00
windows-sandbox: pass workspace roots to runner (#24108)
## Why #23813 switches the Windows sandbox runner path to `PermissionProfile`, but it still left one runtime anchor for resolving symbolic `:workspace_roots` entries. That is not enough once a turn has multiple effective workspace roots: exact entries and deny globs under `:workspace_roots` need to be materialized for every runtime root before the command runner chooses token mode or builds ACL plans. ## What Changed - Replaces the Windows runner/setup `permission_profile_cwd` plumbing with `workspace_roots: Vec<AbsolutePathBuf>`. - Resolves Windows-local `PermissionProfile` data with `materialize_project_roots_with_workspace_roots(...)` instead of the single-cwd helper. - Threads `Config::effective_workspace_roots()` through core execution, unified exec, TUI setup/read-grant flows, app-server setup, app-server `command/exec`, and `debug sandbox` on Windows. - Preserves those workspace roots through the zsh-fork escalation executor instead of rebuilding them from `sandbox_policy_cwd`. - Makes `ExecRequest::new(...)` and the remaining `build_exec_request(...)` helper path take `windows_sandbox_workspace_roots` explicitly so new call sites cannot silently fall back to `vec![cwd]`. - Clarifies the `debug sandbox` non-Windows comment: remaining cwd-dependent resolution still uses `sandbox_policy_cwd`, while `:workspace_roots` entries are already materialized from config roots. - Updates elevated runner IPC `SpawnRequest` to send `workspace_roots` and bumps the framed IPC protocol version to `3` for the payload shape change. - Adds Windows-local resolver coverage for expanding exact and glob `:workspace_roots` entries across multiple roots, plus core helper coverage proving explicit roots are preserved. ## Verification - `cargo check -p codex-windows-sandbox -p codex-core -p codex-tui -p codex-cli -p codex-app-server` - `cargo test -p codex-windows-sandbox` - `cargo test -p codex-core windows_sandbox` - `cargo test -p codex-core unix_escalation` - `cargo test -p codex-app-server windows_sandbox` - `cargo test -p codex-tui windows_sandbox` - `cargo test -p codex-cli debug_sandbox` - `just test -p codex-core unified_exec` - `just test -p codex-core build_exec_request_preserves_windows_workspace_roots` - `env -u CODEX_NETWORK_PROXY_ACTIVE -u CODEX_NETWORK_ALLOW_LOCAL_BINDING just test -p codex-app-server --lib command_exec` - `just test -p codex-windows-sandbox` - `just test -p codex-exec sandbox` - `just fix -p codex-core -p codex-app-server -p codex-windows-sandbox` A local macOS cross-check with `cargo check --target x86_64-pc-windows-msvc ...` did not reach crate Rust code because native dependencies require Windows SDK headers (`windows.h` / `assert.h`) in this environment; Windows CI remains the real target validation. Two local targeted filters compile but do not run assertions on macOS: `env -u CODEX_NETWORK_PROXY_ACTIVE -u CODEX_NETWORK_ALLOW_LOCAL_BINDING just test -p codex-app-server --lib command_exec_processor` matched zero tests, and `just test -p codex-linux-sandbox landlock` matched zero tests because the landlock suite is Linux-only.
This commit is contained in:
1 parent
e7dda8070e
commit
986c60467b
40 files changed
+517
-213
No files matched your search
@@ -26,7 +26,7 @@ use tokio::sync::oneshot;
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) async fn spawn_windows_sandbox_session_elevated_for_permission_profile(
|
||||
permission_profile: &PermissionProfile,
|
||||
permission_profile_cwd: &Path,
|
||||
workspace_roots: &[AbsolutePathBuf],
|
||||
codex_home: &Path,
|
||||
command: Vec<String>,
|
||||
cwd: &Path,
|
||||
@@ -49,10 +49,11 @@ pub(crate) async fn spawn_windows_sandbox_session_elevated_for_permission_profil
|
||||
.iter()
|
||||
.map(AbsolutePathBuf::to_path_buf)
|
||||
.collect::<Vec<_>>();
|
||||
let permissions = ResolvedWindowsSandboxPermissions::try_from_permission_profile_for_cwd(
|
||||
permission_profile,
|
||||
permission_profile_cwd,
|
||||
)?;
|
||||
let permissions =
|
||||
ResolvedWindowsSandboxPermissions::try_from_permission_profile_for_workspace_roots(
|
||||
permission_profile,
|
||||
workspace_roots,
|
||||
)?;
|
||||
let elevated = prepare_elevated_spawn_context_for_permissions(
|
||||
permissions,
|
||||
codex_home,
|
||||
@@ -71,7 +72,7 @@ pub(crate) async fn spawn_windows_sandbox_session_elevated_for_permission_profil
|
||||
cwd: cwd.to_path_buf(),
|
||||
env: env_map.clone(),
|
||||
permission_profile: permission_profile.clone(),
|
||||
permission_profile_cwd: permission_profile_cwd.to_path_buf(),
|
||||
workspace_roots: workspace_roots.to_vec(),
|
||||
codex_home: elevated.sandbox_base.clone(),
|
||||
real_codex_home: codex_home.to_path_buf(),
|
||||
cap_sids: elevated.cap_sids.clone(),
|
||||
|
||||
@@ -271,7 +271,7 @@ fn resize_conpty_handle(hpc: &Arc<StdMutex<Option<HANDLE>>>, size: TerminalSize)
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) async fn spawn_windows_sandbox_session_legacy(
|
||||
permission_profile: &PermissionProfile,
|
||||
permission_profile_cwd: &Path,
|
||||
workspace_roots: &[AbsolutePathBuf],
|
||||
codex_home: &Path,
|
||||
command: Vec<String>,
|
||||
cwd: &Path,
|
||||
@@ -285,7 +285,7 @@ pub(crate) async fn spawn_windows_sandbox_session_legacy(
|
||||
) -> Result<SpawnedProcess> {
|
||||
let common = prepare_legacy_spawn_context(
|
||||
permission_profile,
|
||||
permission_profile_cwd,
|
||||
workspace_roots,
|
||||
codex_home,
|
||||
cwd,
|
||||
&mut env_map,
|
||||
|
||||
@@ -20,7 +20,7 @@ use std::path::PathBuf;
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn spawn_windows_sandbox_session_legacy(
|
||||
permission_profile: &PermissionProfile,
|
||||
permission_profile_cwd: &Path,
|
||||
workspace_roots: &[AbsolutePathBuf],
|
||||
codex_home: &Path,
|
||||
command: Vec<String>,
|
||||
cwd: &Path,
|
||||
@@ -34,7 +34,7 @@ pub async fn spawn_windows_sandbox_session_legacy(
|
||||
) -> Result<SpawnedProcess> {
|
||||
backends::legacy::spawn_windows_sandbox_session_legacy(
|
||||
permission_profile,
|
||||
permission_profile_cwd,
|
||||
workspace_roots,
|
||||
codex_home,
|
||||
command,
|
||||
cwd,
|
||||
@@ -52,7 +52,7 @@ pub async fn spawn_windows_sandbox_session_legacy(
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn spawn_windows_sandbox_session_elevated_for_permission_profile(
|
||||
permission_profile: &PermissionProfile,
|
||||
permission_profile_cwd: &Path,
|
||||
workspace_roots: &[AbsolutePathBuf],
|
||||
codex_home: &Path,
|
||||
command: Vec<String>,
|
||||
cwd: &Path,
|
||||
@@ -69,7 +69,7 @@ pub async fn spawn_windows_sandbox_session_elevated_for_permission_profile(
|
||||
) -> Result<SpawnedProcess> {
|
||||
backends::elevated::spawn_windows_sandbox_session_elevated_for_permission_profile(
|
||||
permission_profile,
|
||||
permission_profile_cwd,
|
||||
workspace_roots,
|
||||
codex_home,
|
||||
command,
|
||||
cwd,
|
||||
|
||||
@@ -79,6 +79,10 @@ fn sandbox_log(codex_home: &Path) -> String {
|
||||
.unwrap_or_else(|err| format!("failed to read {}: {err}", log_path.display()))
|
||||
}
|
||||
|
||||
fn workspace_roots_for(root: &Path) -> Vec<AbsolutePathBuf> {
|
||||
vec![AbsolutePathBuf::from_absolute_path(root).expect("absolute workspace root")]
|
||||
}
|
||||
|
||||
fn wait_for_frame_count(frames_path: &Path, expected_frames: usize) -> Vec<Message> {
|
||||
let deadline = Instant::now() + Duration::from_secs(2);
|
||||
loop {
|
||||
@@ -156,7 +160,7 @@ fn legacy_non_tty_cmd_emits_output() {
|
||||
let permission_profile = PermissionProfile::workspace_write();
|
||||
let spawned = spawn_windows_sandbox_session_legacy(
|
||||
&permission_profile,
|
||||
cwd.as_path(),
|
||||
workspace_roots_for(cwd.as_path()).as_slice(),
|
||||
codex_home.path(),
|
||||
vec![
|
||||
"C:\\Windows\\System32\\cmd.exe".to_string(),
|
||||
@@ -197,7 +201,7 @@ fn legacy_non_tty_cmd_rejects_deny_read_overrides() {
|
||||
let permission_profile = PermissionProfile::workspace_write();
|
||||
let err = spawn_windows_sandbox_session_legacy(
|
||||
&permission_profile,
|
||||
cwd.as_path(),
|
||||
workspace_roots_for(cwd.as_path()).as_slice(),
|
||||
codex_home.path(),
|
||||
vec![
|
||||
"C:\\Windows\\System32\\cmd.exe".to_string(),
|
||||
@@ -237,7 +241,7 @@ fn legacy_non_tty_powershell_emits_output() {
|
||||
let permission_profile = PermissionProfile::workspace_write();
|
||||
let spawned = spawn_windows_sandbox_session_legacy(
|
||||
&permission_profile,
|
||||
cwd.as_path(),
|
||||
workspace_roots_for(cwd.as_path()).as_slice(),
|
||||
codex_home.path(),
|
||||
vec![
|
||||
pwsh.display().to_string(),
|
||||
@@ -423,7 +427,7 @@ fn legacy_capture_powershell_emits_output() {
|
||||
let permission_profile = PermissionProfile::workspace_write();
|
||||
let result = run_windows_sandbox_capture(
|
||||
&permission_profile,
|
||||
cwd.as_path(),
|
||||
workspace_roots_for(cwd.as_path()).as_slice(),
|
||||
codex_home.path(),
|
||||
vec![
|
||||
pwsh.display().to_string(),
|
||||
@@ -515,7 +519,7 @@ fn legacy_tty_powershell_emits_output_and_accepts_input() {
|
||||
let permission_profile = PermissionProfile::workspace_write();
|
||||
let spawned = spawn_windows_sandbox_session_legacy(
|
||||
&permission_profile,
|
||||
cwd.as_path(),
|
||||
workspace_roots_for(cwd.as_path()).as_slice(),
|
||||
codex_home.path(),
|
||||
vec![
|
||||
pwsh.display().to_string(),
|
||||
@@ -569,7 +573,7 @@ fn legacy_tty_cmd_emits_output_and_accepts_input() {
|
||||
let permission_profile = PermissionProfile::workspace_write();
|
||||
let spawned = spawn_windows_sandbox_session_legacy(
|
||||
&permission_profile,
|
||||
cwd.as_path(),
|
||||
workspace_roots_for(cwd.as_path()).as_slice(),
|
||||
codex_home.path(),
|
||||
vec![
|
||||
"C:\\Windows\\System32\\cmd.exe".to_string(),
|
||||
@@ -623,7 +627,7 @@ fn legacy_tty_cmd_default_desktop_emits_output_and_accepts_input() {
|
||||
let permission_profile = PermissionProfile::workspace_write();
|
||||
let spawned = spawn_windows_sandbox_session_legacy(
|
||||
&permission_profile,
|
||||
cwd.as_path(),
|
||||
workspace_roots_for(cwd.as_path()).as_slice(),
|
||||
codex_home.path(),
|
||||
vec![
|
||||
"C:\\Windows\\System32\\cmd.exe".to_string(),
|
||||
|
||||
Reference in new issue
Block a user