fix: support split carveouts in windows elevated sandbox (#14568)

## Summary
- preserve legacy Windows elevated sandbox behavior for existing
policies
- add elevated-only support for split filesystem policies that can be
represented as readable-root overrides, writable-root overrides, and
extra deny-write carveouts
- resolve those elevated filesystem overrides during sandbox transform
and thread them through setup and policy refresh
- keep failing closed for explicit unreadable (`none`) carveouts and
reopened writable descendants under read-only carveouts
- for explicit read-only-under-writable-root carveouts, materialize
missing carveout directories during elevated setup before applying the
deny-write ACL
- document the elevated vs restricted-token support split in the core
README

## Example
Given a split filesystem policy like:

```toml
":root" = "read"
":cwd" = "write"
"./docs" = "read"
"C:/scratch" = "write"
```

the elevated backend now provisions the readable-root overrides,
writable-root overrides, and extra deny-write carveouts during setup and
refresh instead of collapsing back to the legacy workspace-only shape.

If a read-only carveout under a writable root is missing at setup time,
elevated setup creates that carveout as an empty directory before
applying its deny-write ACE; otherwise the sandboxed command could
create it later and bypass the carveout. This is only for explicit
policy carveouts. Best-effort workspace protections like `.codex/` and
`.agents/` still skip missing directories.

A policy like:

```toml
"/workspace" = "write"
"/workspace/docs" = "read"
"/workspace/docs/tmp" = "write"
```

still fails closed, because the elevated backend does not reopen
writable descendants under read-only carveouts yet.

---------

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
viyatb-oai
2026-04-09 17:34:52 -07:00
committed by GitHub
co-authored by Codex
parent 32224878b3
commit b976e701a8
11 changed files with 744 additions and 95 deletions
@@ -133,7 +133,7 @@ pub(super) async fn try_run_zsh_fork(
sandbox_policy,
file_system_sandbox_policy,
network_sandbox_policy,
windows_restricted_token_filesystem_overlay: _windows_restricted_token_filesystem_overlay,
windows_sandbox_filesystem_overrides: _windows_sandbox_filesystem_overrides,
arg0,
} = sandbox_exec_request;
let ParsedShellCommand { script, login, .. } = extract_shell_script(&command)?;
@@ -722,7 +722,7 @@ impl ShellCommandExecutor for CoreShellCommandExecutor {
sandbox_policy: self.sandbox_policy.clone(),
file_system_sandbox_policy: self.file_system_sandbox_policy.clone(),
network_sandbox_policy: self.network_sandbox_policy,
windows_restricted_token_filesystem_overlay: None,
windows_sandbox_filesystem_overrides: None,
arg0: self.arg0.clone(),
},
/*stdout_stream*/ None,