Protect workspace .agents directory in Windows sandbox (#11970)

The Mac and Linux implementations of the sandbox recently added write
protections for `.codex` and `.agents` subdirectories in all writable
roots. When adding documentation for this, I noticed that this change
was never made for the Windows sandbox.

Summary
- make compute_allow_paths treat .codex/.agents as protected alongside
.git, and cover their behavior in new tests
- wire protect_workspace_agents_dir through the sandbox lib and setup
path to apply deny ACEs when `.agents` exists
- factor shared ACL logic for workspace subdirectories
This commit is contained in:
Eric Traut
2026-02-17 09:40:46 -08:00
committed by GitHub
parent 31906cdb4d
commit 5296e06b61
4 changed files with 85 additions and 11 deletions

View File

@@ -16,6 +16,7 @@ use codex_windows_sandbox::is_command_cwd_root;
use codex_windows_sandbox::load_or_create_cap_sids;
use codex_windows_sandbox::log_note;
use codex_windows_sandbox::path_mask_allows;
use codex_windows_sandbox::protect_workspace_agents_dir;
use codex_windows_sandbox::protect_workspace_codex_dir;
use codex_windows_sandbox::sandbox_dir;
use codex_windows_sandbox::sandbox_secrets_dir;
@@ -788,9 +789,9 @@ fn run_setup_full(payload: &Payload, log: &mut File, sbx_dir: &Path) -> Result<(
}
}
// Protect the current workspace's `.codex` directory from tampering (write/delete) by using a
// workspace-specific capability SID. If `.codex` doesn't exist yet, skip it (it will be picked
// up on the next refresh).
// Protect the current workspace's `.codex` and `.agents` directories from tampering
// (write/delete) by using a workspace-specific capability SID. If a directory doesn't exist
// yet, skip it (it will be picked up on the next refresh).
match unsafe { protect_workspace_codex_dir(&payload.command_cwd, workspace_psid) } {
Ok(true) => {
let cwd_codex = payload.command_cwd.join(".codex");
@@ -812,6 +813,30 @@ fn run_setup_full(payload: &Payload, log: &mut File, sbx_dir: &Path) -> Result<(
)?;
}
}
match unsafe { protect_workspace_agents_dir(&payload.command_cwd, workspace_psid) } {
Ok(true) => {
let cwd_agents = payload.command_cwd.join(".agents");
log_line(
log,
&format!(
"applied deny ACE to protect workspace .agents {}",
cwd_agents.display()
),
)?;
}
Ok(false) => {}
Err(err) => {
let cwd_agents = payload.command_cwd.join(".agents");
refresh_errors.push(format!(
"deny ACE failed on {}: {err}",
cwd_agents.display()
));
log_line(
log,
&format!("deny ACE failed on {}: {err}", cwd_agents.display()),
)?;
}
}
unsafe {
if !sandbox_group_psid.is_null() {
LocalFree(sandbox_group_psid as HLOCAL);