Preserve Windows sandbox identity during credential retry (#29624)

## Summary

- recognize stale Windows sandbox credentials from both runner logon and
child startup failures
- refresh credentials once without changing the original command,
permissions, file rules, desktop mode, or managed-network identity
- add a Windows regression test that forces error 1312 and inspects the
real retry arguments

## Why

Elevated unified exec starts commands in two steps:

```text
Codex -> sandbox command runner -> requested command
```

Either process start can fail when Windows invalidates the sandbox logon
session. The child-side failure was previously returned as text, so the
parent could not reliably recognize Windows error 1312.

The existing retry also refreshed credentials with `proxy_enforced =
false`, even when the original request used managed networking. That
could change the selected Windows sandbox identity from offline to
online during the retry.

## How

- carry the failure stage and numeric Windows error code through the
command-runner IPC protocol
- preserve native `CreateProcessAsUserW` error codes instead of parsing
error messages
- keep every retry-sensitive field in one request and use it for both
attempts
- retry exactly once after refreshing credentials, then return the
second failure
- share the retry rule with the elevated capture path

The Windows test injects error 1312 on both attempts and verifies:

- two spawn attempts and one credential refresh
- stale credentials are replaced by refreshed credentials
- both attempts receive the same command, environment, cwd, permissions,
roots, deny paths, TTY settings, and private-desktop mode
- credential refresh receives the original `proxy_enforced` value

## Tests

- `just test -p codex-windows-sandbox`
- the new Windows-only regression test is included in the Windows
nextest CI archive
This commit is contained in:
jif authored and GitHub committed 2026-06-24 20:20:52 +01:00
1 parent 5013d10824
commit 4907f0c2c3
9 files changed
+488 -103

No files matched your search

+3 -2
View File
@@ -4,6 +4,7 @@ use crate::proc_thread_attr::ProcThreadAttributeList;
use crate::winutil::argv_to_command_line;
use crate::winutil::format_last_error;
use crate::winutil::to_wide;
use anyhow::Context;
use anyhow::Result;
use anyhow::anyhow;
use std::collections::HashMap;
@@ -146,7 +147,7 @@ pub unsafe fn create_process_as_user(
creation_flags,
);
logging::debug_log(&msg, logs_base_dir);
return Err(anyhow!("CreateProcessAsUserW failed: {err}"));
return Err(std::io::Error::from_raw_os_error(err)).context(msg);
}
Ok(CreatedProcess {
process_info: pi,
@@ -187,7 +188,7 @@ pub unsafe fn create_process_as_user(
creation_flags,
);
logging::debug_log(&msg, logs_base_dir);
return Err(anyhow!("CreateProcessAsUserW failed: {err}"));
return Err(std::io::Error::from_raw_os_error(err)).context(msg);
}
Ok(CreatedProcess {
process_info: pi,