windows-sandbox: send permission profiles to elevated runner (#22918)

## Why

This is the next PR in the Windows sandbox migration stack after #22896.
The bottom PR introduces a Windows-local resolved permissions helper
while existing callers still start from legacy `SandboxPolicy`. This PR
moves the elevated runner IPC boundary to `PermissionProfile`, which
makes the direction of the stack visible without changing the public
core call sites yet.

Because that changes the CLI-to-command-runner message shape, the framed
IPC protocol version is bumped in the same PR so the boundary change is
explicit.

## What changed

- Replaced elevated IPC `policy_json_or_preset`/`sandbox_policy_cwd`
fields with `permission_profile`/`permission_profile_cwd`.
- Bumped the elevated command-runner IPC protocol to
`IPC_PROTOCOL_VERSION = 2` and switched parent/runner frames to use the
shared constant.
- Converted the parent elevated paths from the parsed legacy policy into
a materialized `PermissionProfile` before sending the runner request.
- Added `WindowsSandboxTokenMode` resolution for managed
`PermissionProfile` values and made the runner choose read-only vs
writable-root capability tokens from that resolved profile.
- Rejected disabled, external, unrestricted, and full-disk-write
profiles before token selection.
- Added IPC JSON coverage for tagged `PermissionProfile` payloads and
token-mode unit coverage for the resolved permission helper.

## Verification

- `cargo test -p codex-windows-sandbox`
- `just fix -p codex-windows-sandbox`
- `cargo check -p codex-windows-sandbox --target x86_64-pc-windows-msvc
--tests` was attempted locally but blocked before crate type-checking
because the macOS compiler environment lacks Windows C headers such as
`windows.h` and `assert.h`; GitHub Windows CI is the required
verification for the runner path.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/22918).
* #23715
* #23714
* #23167
* #22923
* __->__ #22918
This commit is contained in:
Michael Bolin authored and GitHub committed 2026-05-20 12:41:06 -07:00
1 parent cb05de6724
commit 729bdf3c8d
8 files changed
+273 -27

No files matched your search

@@ -5,11 +5,13 @@ use super::windows_common::start_runner_stdin_writer;
use super::windows_common::start_runner_stdout_reader;
use crate::ipc_framed::EmptyPayload;
use crate::ipc_framed::FramedMessage;
use crate::ipc_framed::IPC_PROTOCOL_VERSION;
use crate::ipc_framed::Message;
use crate::ipc_framed::SpawnRequest;
use crate::runner_client::spawn_runner_transport;
use crate::spawn_prep::prepare_elevated_spawn_context;
use anyhow::Result;
use codex_protocol::models::PermissionProfile;
use codex_utils_absolute_path::AbsolutePathBuf;
use codex_utils_pty::ProcessDriver;
use codex_utils_pty::SpawnedProcess;
@@ -60,12 +62,16 @@ pub(crate) async fn spawn_windows_sandbox_session_elevated(
&deny_write_paths_override,
)?;
let permission_profile = PermissionProfile::from_legacy_sandbox_policy_for_cwd(
&elevated.common.policy,
sandbox_policy_cwd,
);
let spawn_request = SpawnRequest {
command: command.clone(),
cwd: cwd.to_path_buf(),
env: env_map.clone(),
policy_json_or_preset: policy_json_or_preset.to_string(),
sandbox_policy_cwd: sandbox_policy_cwd.to_path_buf(),
permission_profile,
permission_profile_cwd: sandbox_policy_cwd.to_path_buf(),
codex_home: elevated.common.sandbox_base.clone(),
real_codex_home: codex_home.to_path_buf(),
cap_sids: elevated.cap_sids.clone(),
@@ -106,7 +112,7 @@ pub(crate) async fn spawn_windows_sandbox_session_elevated(
let outbound_tx = outbound_tx.clone();
Some(Box::new(move || {
let _ = outbound_tx.send(FramedMessage {
version: 1,
version: IPC_PROTOCOL_VERSION,
message: Message::Terminate {
payload: EmptyPayload::default(),
},
@@ -1,5 +1,6 @@
use crate::ipc_framed::EmptyPayload;
use crate::ipc_framed::FramedMessage;
use crate::ipc_framed::IPC_PROTOCOL_VERSION;
use crate::ipc_framed::Message;
use crate::ipc_framed::OutputStream;
use crate::ipc_framed::ResizePayload;
@@ -70,7 +71,7 @@ pub(crate) fn start_runner_stdin_writer(
bytes
};
let msg = FramedMessage {
version: 1,
version: IPC_PROTOCOL_VERSION,
message: Message::Stdin {
payload: StdinPayload {
data_b64: encode_bytes(&bytes),
@@ -83,7 +84,7 @@ pub(crate) fn start_runner_stdin_writer(
}
if stdin_open {
let _ = outbound_tx.send(FramedMessage {
version: 1,
version: IPC_PROTOCOL_VERSION,
message: Message::CloseStdin {
payload: EmptyPayload::default(),
},
@@ -165,7 +166,7 @@ pub(crate) fn make_runner_resizer(
Box::new(move |size: TerminalSize| {
outbound_tx
.send(FramedMessage {
version: 1,
version: IPC_PROTOCOL_VERSION,
message: Message::Resize {
payload: ResizePayload {
rows: size.rows,