mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
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:
9 files changed
+488
-103
No files matched your search
@@ -44,7 +44,7 @@ mod windows_impl {
|
||||
use crate::logging::log_start;
|
||||
use crate::logging::log_success;
|
||||
use crate::resolved_permissions::ResolvedWindowsSandboxPermissions;
|
||||
use crate::runner_client::is_stale_sandbox_creds_error;
|
||||
use crate::runner_client::retry_runner_spawn_once;
|
||||
use crate::runner_client::spawn_runner_transport;
|
||||
use crate::sandbox_utils::ensure_codex_home_exists;
|
||||
use crate::sandbox_utils::inject_git_safe_directory;
|
||||
@@ -139,7 +139,7 @@ mod windows_impl {
|
||||
|
||||
let logs_base_dir: Option<&Path> = Some(sandbox_base.as_path());
|
||||
log_start(&command, logs_base_dir);
|
||||
let mut sandbox_creds = require_logon_sandbox_creds(
|
||||
let sandbox_creds = require_logon_sandbox_creds(
|
||||
&permissions,
|
||||
cwd,
|
||||
&env_map,
|
||||
@@ -195,16 +195,19 @@ mod windows_impl {
|
||||
stdin_open: false,
|
||||
use_private_desktop,
|
||||
};
|
||||
let transport = match spawn_runner_transport(
|
||||
codex_home,
|
||||
cwd,
|
||||
&sandbox_creds,
|
||||
logs_base_dir,
|
||||
spawn_request.clone(),
|
||||
) {
|
||||
Ok(transport) => transport,
|
||||
Err(err) if is_stale_sandbox_creds_error(&err) => {
|
||||
sandbox_creds = refresh_logon_sandbox_creds(
|
||||
let transport = retry_runner_spawn_once(
|
||||
sandbox_creds,
|
||||
|sandbox_creds| {
|
||||
spawn_runner_transport(
|
||||
codex_home,
|
||||
cwd,
|
||||
&sandbox_creds,
|
||||
logs_base_dir,
|
||||
spawn_request.clone(),
|
||||
)
|
||||
},
|
||||
|| {
|
||||
refresh_logon_sandbox_creds(
|
||||
&permissions,
|
||||
cwd,
|
||||
&env_map,
|
||||
@@ -216,17 +219,9 @@ mod windows_impl {
|
||||
&deny_write_paths_override,
|
||||
proxy_enforced,
|
||||
crate::WindowsSandboxProxySettingsMode::Reconcile,
|
||||
)?;
|
||||
spawn_runner_transport(
|
||||
codex_home,
|
||||
cwd,
|
||||
&sandbox_creds,
|
||||
logs_base_dir,
|
||||
spawn_request,
|
||||
)?
|
||||
}
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
)
|
||||
},
|
||||
)?;
|
||||
let (pipe_write, mut pipe_read) = transport.into_files();
|
||||
let cancel_writer = spawn_cancel_writer(&pipe_write, cancellation)?;
|
||||
|
||||
|
||||
Reference in new issue
Block a user