Simplify legacy Windows sandbox ACL persistence (#22569)

## Why

The legacy Windows sandbox still carried a `persist_aces` mode switch,
even though the only path that meaningfully applies filesystem ACEs
today is `workspace-write`, which already uses the persistent behavior.
Legacy read-only sessions rely on the read-only capability SID rather
than per-command filesystem ACE mutation, so the temporary cleanup
branch had become conceptual overhead without a corresponding behavioral
need.

Removing that split makes the ACL lifecycle match the current sandbox
model more directly and trims the guard/revocation plumbing from the
legacy launcher paths.

## What changed

- Removed the `persist_aces` parameter from legacy ACL preparation.
- Made legacy deny-read handling always use the persistent
reconciliation path.
- Dropped guard tracking and post-exit ACE revocation from both capture
and unified-exec legacy flows.
- Kept workspace `.codex` / `.agents` protection tied directly to
`WorkspaceWrite` instead of an intermediate persistence flag.

## Verification

- `cargo fmt -p codex-windows-sandbox`
- `git diff --check`
- `cargo test -p codex-windows-sandbox`
  - 85 passed, 2 ignored, 2 (unrelated) failed locally.
This commit is contained in:
iceweasel-oai authored and GitHub committed 2026-05-18 11:00:03 -07:00
1 parent 9286ff2805
commit b1c13b6fe5
3 files changed
+21 -103

No files matched your search

@@ -1,6 +1,5 @@
use super::windows_common::finish_driver_spawn;
use super::windows_common::normalize_windows_tty_input;
use crate::acl::revoke_ace;
use crate::conpty::ConptyInstance;
use crate::conpty::spawn_conpty_process_as_user;
use crate::desktop::LaunchDesktop;
@@ -16,7 +15,6 @@ use crate::spawn_prep::apply_legacy_session_acl_rules;
use crate::spawn_prep::legacy_session_capability_roots;
use crate::spawn_prep::prepare_legacy_session_security;
use crate::spawn_prep::prepare_legacy_spawn_context;
use crate::token::LocalSid;
use anyhow::Result;
use codex_utils_absolute_path::AbsolutePathBuf;
use codex_utils_pty::ProcessDriver;
@@ -24,7 +22,6 @@ use codex_utils_pty::SpawnedProcess;
use codex_utils_pty::TerminalSize;
use std::collections::HashMap;
use std::path::Path;
use std::path::PathBuf;
use std::ptr;
use std::sync::Arc;
use std::sync::Mutex as StdMutex;
@@ -206,7 +203,6 @@ fn finalize_exit(
process_handle: Arc<StdMutex<Option<HANDLE>>>,
thread_handle: HANDLE,
output_join: std::thread::JoinHandle<()>,
guards: Vec<(PathBuf, String)>,
logs_base_dir: Option<&Path>,
command: Vec<String>,
) {
@@ -242,14 +238,6 @@ fn finalize_exit(
} else {
log_failure(&command, &format!("exit code {exit_code}"), logs_base_dir);
}
unsafe {
for (path, cap_sid) in guards {
if let Ok(sid) = LocalSid::from_string(&cap_sid) {
revoke_ace(&path, sid.as_ptr());
}
}
}
}
fn resize_conpty_handle(hpc: &Arc<StdMutex<Option<HANDLE>>>, size: TerminalSize) -> Result<()> {
@@ -325,8 +313,7 @@ pub(crate) async fn spawn_windows_sandbox_session_legacy(
prepare_legacy_session_security(&common.policy, codex_home, cwd, capability_roots)?;
allow_null_device_for_workspace_write(common.is_workspace_write);
let persist_aces = common.is_workspace_write;
let guards = apply_legacy_session_acl_rules(
apply_legacy_session_acl_rules(
&common.policy,
sandbox_policy_cwd,
codex_home,
@@ -339,7 +326,6 @@ pub(crate) async fn spawn_windows_sandbox_session_legacy(
readonly_sid_str: security.readonly_sid_str.as_deref(),
write_root_sids: &security.write_root_sids,
},
persist_aces,
)?;
let (writer_tx, writer_rx) = mpsc::channel::<Vec<u8>>(128);
@@ -375,13 +361,6 @@ pub(crate) async fn spawn_windows_sandbox_session_legacy(
Ok(handles) => handles,
Err(err) => {
unsafe {
if !persist_aces {
for (path, cap_sid) in &guards {
if let Ok(sid) = LocalSid::from_string(cap_sid) {
revoke_ace(path, sid.as_ptr());
}
}
}
CloseHandle(security.h_token);
}
return Err(err);
@@ -392,7 +371,6 @@ pub(crate) async fn spawn_windows_sandbox_session_legacy(
let process_handle = Arc::new(StdMutex::new(Some(pi.hProcess)));
let wait_handle = Arc::clone(&process_handle);
let command_for_wait = command.clone();
let guards_for_wait = if persist_aces { Vec::new() } else { guards };
let hpc_for_wait = hpc_handle.clone();
std::thread::spawn(move || {
let _desktop = desktop;
@@ -423,7 +401,6 @@ pub(crate) async fn spawn_windows_sandbox_session_legacy(
wait_handle,
pi.hThread,
output_join,
guards_for_wait,
common.logs_base_dir.as_deref(),
command_for_wait,
);