WindowsSandbox架构
Windows 沙箱的核心不是“创建一个 restricted token”。一次命令执行先携带完整的 PermissionProfile、workspace roots、网络代理状态、TTY/stdio 和取消参数,进入 executor-native 的统一 spawn 接口;随后由 Windows backend 根据 WindowsSandboxLevel 选择 unelevated restricted-token 或 elevated command-runner。两条路径共享同一份权限快照,却在“谁建立 ACL、谁创建进程、谁持有生命周期句柄”上有明确分工。
本文不把 Windows-only 行为伪装成当前主机实测。源码和测试能够证明请求字段、backend 选择、权限可表达性检查、ACL/SID 组装、elevated IPC 帧和 Job Object 的控制流;UAC、ACL、firewall、ConPTY 和 Windows namespace 的系统效果仍需 Windows target 执行。
阅读前可先查看跨平台Sandbox抽象了解 SandboxType 与 executor owner,再查看权限审批沙箱三层模型理解 permission profile 如何进入单次执行请求。
1. 配置解析到等级
Core 同时支持显式配置和历史 feature key。显式 windows.sandbox 优先;没有显式值时,WindowsSandboxElevated 优先于 WindowsSandbox,最终映射为 Elevated、RestrictedToken 或 Disabled。private desktop 则是独立配置,默认开启。
源码位置:codex-rs/core/src/windows_sandbox.rs :: WindowsSandboxLevelExt::from_config、WindowsSandboxLevelExt::from_features
impl WindowsSandboxLevelExt for WindowsSandboxLevel {
fn from_config(config: &Config) -> WindowsSandboxLevel {
match config.permissions.windows_sandbox_mode {
Some(WindowsSandboxModeToml::Elevated) => WindowsSandboxLevel::Elevated,
Some(WindowsSandboxModeToml::Unelevated) => WindowsSandboxLevel::RestrictedToken,
None => Self::from_features(&config.features),
}
}
fn from_features(features: &Features) -> WindowsSandboxLevel {
if features.enabled(Feature::WindowsSandboxElevated) {
return WindowsSandboxLevel::Elevated;
}
if features.enabled(Feature::WindowsSandbox) {
WindowsSandboxLevel::RestrictedToken
} else {
WindowsSandboxLevel::Disabled
}
}
}源码位置:codex-rs/core/src/windows_sandbox.rs :: resolve_windows_sandbox_mode、resolve_windows_sandbox_private_desktop
pub fn resolve_windows_sandbox_mode(cfg: &ConfigToml) -> Option<WindowsSandboxModeToml> {
cfg.windows
.as_ref()
.and_then(|windows| windows.sandbox)
.or_else(|| legacy_windows_sandbox_mode(cfg.features.as_ref()))
}
pub fn resolve_windows_sandbox_private_desktop(cfg: &ConfigToml) -> bool {
cfg.windows
.as_ref()
.and_then(|windows| windows.sandbox_private_desktop)
.unwrap_or(true)
}这一步只决定“请求使用什么等级”,并不创建 token 或 ACL。真正的执行约束在后续 PermissionProfile 解析和 executor spawn 阶段建立。
2. 权限快照与边界
Windows backend 先把用户层 PermissionProfile 解析成 ResolvedWindowsSandboxPermissions。只有 managed、restricted filesystem profile 能进入 Windows sandbox;symbolic :workspace_roots 会在解析时绑定调用方传入的 roots。token mode 进一步区分“只读 capability”与“按 writable roots 分配 capability SID”。
源码位置:codex-rs/windows-sandbox-rs/src/resolved_permissions.rs :: ResolvedWindowsSandboxPermissions::try_from_permission_profile_for_workspace_roots、token_mode_for_permission_profile
pub fn token_mode_for_permission_profile(
permission_profile: &PermissionProfile,
workspace_roots: &[AbsolutePathBuf],
cwd: &Path,
env_map: &HashMap<String, String>,
) -> Result<WindowsSandboxTokenMode> {
let permissions =
ResolvedWindowsSandboxPermissions::try_from_permission_profile_for_workspace_roots(
permission_profile,
workspace_roots,
)?;
if permissions.file_system.has_full_disk_write_access() {
anyhow::bail!(
"permission profile requests full-disk filesystem writes, which cannot be enforced by the Windows sandbox"
);
}
if permissions.writable_roots_for_cwd(cwd, env_map).is_empty() {
Ok(WindowsSandboxTokenMode::ReadOnlyCapability)
} else {
Ok(WindowsSandboxTokenMode::WritableRootsCapability)
}
}
impl ResolvedWindowsSandboxPermissions {
pub fn try_from_permission_profile_for_workspace_roots(
permission_profile: &PermissionProfile,
workspace_roots: &[AbsolutePathBuf],
) -> Result<Self> {
let mut permissions = Self::try_from_permission_profile(permission_profile)?;
permissions.file_system = permissions
.file_system
.materialize_project_roots_with_workspace_roots(workspace_roots);
Ok(permissions)
}
}Windows 的限制不是抽象上的“全部或无”:unelevated token 能处理某些 writable-root 投影,却不能让 capability SID 的 deny-read ACE 参与读检查;split read restriction、deny-read 和某些重开的 writable descendant 必须交给 elevated override。sandboxing/src/windows.rs 因此在启动前比较 legacy projection 与 split policy,无法表达时返回错误并拒绝无沙箱运行。
源码位置:codex-rs/sandboxing/src/windows.rs :: resolve_windows_restricted_token_filesystem_overrides
if !windows_policy_has_root_read_access(&file_system_sandbox_policy, sandbox_policy_cwd) {
return Err(
"windows unelevated restricted-token sandbox cannot enforce split filesystem read restrictions directly; refusing to run unsandboxed"
.to_string(),
);
}
let additional_deny_read_paths = codex_windows_sandbox::resolve_windows_deny_read_paths(
&file_system_sandbox_policy,
sandbox_policy_cwd,
)?;
if !additional_deny_read_paths.is_empty() {
return Err(
"windows unelevated restricted-token sandbox cannot enforce deny-read restrictions directly; refusing to run unsandboxed"
.to_string(),
);
}3. 统一spawn入口
SandboxType::WindowsRestrictedToken 不再由不同调用方各自拼装参数。sandboxing::spawn_process 把权限快照、workspace roots、proxy enforcing、restricting SID、filesystem overrides、TTY 和 stdin 组装为 WindowsSandboxSessionRequest,再调用 codex-windows-sandbox。非 Windows 编译目标保留明确错误 stub,而不是模拟成功。
源码位置:codex-rs/sandboxing/src/spawn.rs :: WindowsSandboxSpawnRequest、spawn_process
pub struct WindowsSandboxSpawnRequest<'a> {
pub permission_profile: &'a PermissionProfile,
pub workspace_roots: &'a [AbsolutePathBuf],
pub windows_sandbox_level: WindowsSandboxLevel,
pub proxy_enforced: bool,
pub network_proxy_restricting_sid: Option<&'a str>,
pub proxy_settings_mode: WindowsSandboxProxySettingsMode,
pub filesystem_overrides: Option<&'a WindowsSandboxFilesystemOverrides>,
pub use_private_desktop: bool,
}源码位置:codex-rs/sandboxing/src/spawn.rs :: spawn_process
pub async fn spawn_process(request: SpawnRequest<'_>) -> Result<SpawnedProcess> {
if request.sandbox == SandboxType::WindowsRestrictedToken {
#[cfg(target_os = "windows")]
{
let windows = request
.windows_sandbox
.context("missing Windows sandbox spawn request")?;
let codex_home = codex_utils_home_dir::find_codex_home()
.context("windows sandbox: failed to resolve codex_home")?;
let empty_paths = &[];
let overrides = windows.filesystem_overrides;
return codex_windows_sandbox::spawn_windows_sandbox_session_for_level(
codex_windows_sandbox::WindowsSandboxSessionRequest {
permission_profile: windows.permission_profile,
workspace_roots: windows.workspace_roots,
codex_home: codex_home.as_path(),
command: request.command.to_vec(),
cwd: request.cwd,
env_map: request.env.clone(),
windows_sandbox_level: windows.windows_sandbox_level,
proxy_enforced: windows.proxy_enforced,
network_proxy_restricting_sid: windows
.network_proxy_restricting_sid
.map(str::to_owned),
proxy_settings_mode: windows.proxy_settings_mode,
timeout_ms: None,
read_roots_override: overrides
.and_then(|value| value.read_roots_override.as_deref()),
read_roots_include_platform_defaults: overrides
.is_some_and(|value| value.read_roots_include_platform_defaults),
write_roots_override: overrides
.and_then(|value| value.write_roots_override.as_deref()),
deny_read_paths_override: overrides.map_or(empty_paths, |value| {
value.additional_deny_read_paths.as_slice()
}),
deny_write_paths_override: overrides.map_or(empty_paths, |value| {
value.additional_deny_write_paths.as_slice()
}),
tty: request.tty,
stdin_open: request.stdin_open,
use_private_desktop: windows.use_private_desktop,
},
)
.await;
}
#[cfg(not(target_os = "windows"))]
anyhow::bail!("Windows sandbox process spawn is unavailable on this platform");
}
}这里展示的是 Windows 分支的完整连续实现;函数随后在源码中继续处理其他 sandbox 类型的普通 PTY/pipe spawn。非 Windows 编译目标的 Windows sandbox 分支则明确返回平台不可用错误。
4. Legacy token路径
legacy backend 的前置顺序是:解析权限 → 规范化环境 → 生成 capability roots → 创建 restricted token → 把 allow/deny 规则写入 ACL → 创建进程。只读 profile 使用 readonly SID;workspace-write 使用每个 writable root 的 capability SID。deny-read override 在这条路径上被拒绝,因为 WRITE_RESTRICTED token 不能让 capability SID deny-read ACE 成为读检查的权威来源。
源码位置:codex-rs/windows-sandbox-rs/src/spawn_prep.rs :: prepare_legacy_session_security
pub(crate) fn prepare_legacy_session_security(
uses_write_capabilities: bool,
codex_home: &Path,
cwd: &Path,
capability_roots: impl IntoIterator<Item = PathBuf>,
) -> Result<LegacySessionSecurity> {
let caps = load_or_create_cap_sids(codex_home)?;
let (h_token, readonly_sid, readonly_sid_str, write_root_sids) = unsafe {
if uses_write_capabilities {
let write_root_sids = root_capability_sids(codex_home, cwd, capability_roots)?;
if write_root_sids.is_empty() {
anyhow::bail!("workspace-write sandbox has no writable root capability SIDs");
}
let base = get_current_token_for_restriction()?;
let cap_ptrs: Vec<*mut c_void> = write_root_sids
.iter()
.map(|root| root.sid.as_ptr())
.collect();
let h_token = create_workspace_write_token_with_caps_from(base, cap_ptrs.as_slice());
CloseHandle(base);
let h_token = h_token?;
(h_token, None, None, write_root_sids)
} else {
let psid = LocalSid::from_string(&caps.readonly)?;
let (h_token, _psid) = create_readonly_token_with_cap(psid.as_ptr())?;
(h_token, Some(psid), Some(caps.readonly), Vec::new())
}
};
Ok(LegacySessionSecurity {
h_token,
readonly_sid,
readonly_sid_str,
write_root_sids,
})
}源码位置:codex-rs/windows-sandbox-rs/src/unified_exec/backends/legacy.rs :: spawn_windows_sandbox_session_legacy
let common = prepare_legacy_spawn_context(
permission_profile,
workspace_roots,
codex_home,
cwd,
&mut env_map,
&command,
SpawnPrepOptions {
inherit_path: false,
add_git_safe_directory: false,
},
)?;
if !common.permissions.has_full_disk_read_access() {
anyhow::bail!("Restricted read-only access requires the elevated Windows sandbox backend");
}
if !additional_deny_read_paths.is_empty() {
anyhow::bail!("deny-read overrides require the elevated Windows sandbox backend");
}
let capability_roots = legacy_session_capability_roots(
&common.permissions,
&common.current_dir,
&env_map,
codex_home,
);
let security = prepare_legacy_session_security(
common.uses_write_capabilities,
codex_home,
cwd,
capability_roots,
)?;后续 apply_legacy_session_acl_rules 会把 allow roots、deny-write carveouts、persistent deny-read(仅在可用 SID 语义下)和 .codex/.agents 保护写入 ACL,然后才调用 token spawn。失败发生在这条路径时会返回错误,不会调用普通未沙箱 spawn。
5. Job Object进程树
legacy backend 的 TTY 分支通过 ConPTY 创建进程,非 TTY 分支通过 pipes 创建进程;两者都要求返回 Job Object。ProcessDriver 的 terminator 终止 job,等待线程在超时或取消时优先杀整个进程树,只有 Job API 失败才退回 TerminateProcess 杀根进程。
源码位置:codex-rs/windows-sandbox-rs/src/unified_exec/backends/legacy.rs :: spawn_legacy_process、terminate_job_or_process
fn terminate_job_or_process(
job: &JobObject,
process_handle: &Arc<StdMutex<Option<HANDLE>>>,
logs_base_dir: Option<&Path>,
) {
if let Err(job_err) = job.terminate() {
log_note(
&format!("legacy spawn failed to terminate process tree: {job_err}"),
logs_base_dir,
);
if let Ok(guard) = process_handle.lock()
&& let Some(handle) = guard.as_ref()
&& unsafe { TerminateProcess(*handle, 1) } == 0
{
log_note(
&format!(
"legacy spawn failed to terminate root process: {}",
unsafe { GetLastError() }
),
logs_base_dir,
);
}
}
}源码位置:codex-rs/utils/pty/src/win/job.rs :: JobObject::create、JobObject::terminate
pub fn create() -> io::Result<Self> {
let handle = unsafe { CreateJobObjectW(std::ptr::null_mut(), std::ptr::null()) };
if handle.is_null() {
return Err(io::Error::last_os_error());
}
let handle = unsafe { OwnedHandle::from_raw_handle(handle.cast()) };
Self::set_limit_flags(
&handle,
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_BREAKAWAY_OK,
)?;
Ok(Self {
handle,
preserve_descendants: Mutex::new(false),
})
}
pub fn terminate(&self) -> io::Result<()> {
let preserve_descendants = self
.preserve_descendants
.lock()
.map_err(|_| io::Error::other("job state lock poisoned"))?;
if *preserve_descendants {
return Ok(());
}
let terminated = unsafe {
TerminateJobObject(self.handle.as_raw_handle().cast(), /*uExitCode*/ 1)
};
if terminated == 0 {
Err(io::Error::last_os_error())
} else {
Ok(())
}
}Job Object 的 KILL_ON_JOB_CLOSE 还提供句柄关闭后的兜底回收;preserve_descendants 则用于根进程先退出、但 session 仍需保留子孙的场景。这个细节解释了为什么 Windows sandbox 的生命周期不能只用一个 PID 表示。
6. Elevated setup
elevated backend 不把 ACL 操作塞进父进程的 token。它先生成或刷新 sandbox credentials,再把 resolved roots、deny paths、proxy ports、offline/online 用户、cwd 和 setup mode 编码成 ElevationPayload。setup refresh 使用 singleflight:相同 payload 的并发调用共享一次 helper 执行和结果。
源码位置:codex-rs/windows-sandbox-rs/src/setup.rs :: run_setup_singleflight
fn run_setup_singleflight(key: String, run: impl FnOnce() -> Result<()>) -> Result<()> {
let flights = SETUP_FLIGHTS.get_or_init(|| Mutex::new(HashMap::new()));
let (flight, is_leader) = {
let mut flights = flights
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
match flights.get(&key) {
Some(flight) => (Arc::clone(flight), false),
None => {
let flight = Arc::new(SetupFlight::pending());
flights.insert(key.clone(), Arc::clone(&flight));
(flight, true)
}
}
};
if !is_leader {
return flight.wait();
}
let result = run();
let shared_result = match &result {
Ok(()) => Ok(()),
Err(error) => Err(SharedSetupError::from_error(error)),
};
flight.complete(shared_result);
let mut flights = flights
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if flights
.get(&key)
.is_some_and(|current| Arc::ptr_eq(current, &flight))
{
flights.remove(&key);
}
result
}源码位置:codex-rs/windows-sandbox-rs/src/setup.rs :: run_setup_refresh_inner
fn run_setup_refresh_inner(
request: SandboxSetupRequest<'_>,
overrides: SetupRootOverrides,
offline_proxy_settings_override: Option<&OfflineProxySettings>,
) -> Result<()> {
if !request.permissions.is_enforceable_by_windows_sandbox() {
anyhow::bail!("unsupported filesystem permissions for Windows sandbox setup");
}
let (read_roots, write_roots) = build_payload_roots(&request, &overrides);
let deny_read_paths = build_payload_deny_read_paths(overrides.deny_read_paths);
let deny_write_paths = build_payload_deny_write_paths(&request, overrides.deny_write_paths);
let offline_proxy_settings =
offline_proxy_settings_for_request(&request, offline_proxy_settings_override);
let payload = ElevationPayload {
version: SETUP_VERSION,
offline_username: OFFLINE_USERNAME.to_string(),
online_username: ONLINE_USERNAME.to_string(),
codex_home: request.codex_home.to_path_buf(),
command_cwd: request.command_cwd.to_path_buf(),
read_roots,
write_roots,
deny_read_paths,
deny_write_paths,
proxy_ports: offline_proxy_settings.proxy_ports,
allow_local_binding: offline_proxy_settings.allow_local_binding,
otel: None,
real_user: std::env::var("USERNAME").unwrap_or_else(|_| "Administrators".to_string()),
mode: SetupMode::Full,
refresh_only: true,
};
let json = serde_json::to_vec(&payload)?;
let b64 = BASE64_STANDARD.encode(json);
run_setup_singleflight(b64.clone(), || {
run_setup_refresh_payload(&b64, request.codex_home)
})
}refresh_only: true 的含义是刷新 ACL/配置,不请求 UAC elevation;真正需要 elevated command runner 时,后续 credentials 和 runner pipe 再承担进程创建。
7. Elevated runner
elevated backend 将 SpawnRequest 发给 command runner。请求包含命令、cwd、环境、原始 PermissionProfile、workspace roots、sandbox home、capability SIDs、可选的 network restricting SID、超时、TTY 和 private desktop。父进程只在收到 SpawnReady 后把 pipe 转换为统一 ProcessDriver。
源码位置:codex-rs/windows-sandbox-rs/src/elevated/ipc_framed.rs :: Message、SpawnRequest
pub enum Message {
SpawnRequest { payload: Box<SpawnRequest> },
SpawnReady { payload: SpawnReady },
Output { payload: OutputPayload },
Stdin { payload: StdinPayload },
CloseStdin { payload: EmptyPayload },
Resize { payload: ResizePayload },
Exit { payload: ExitPayload },
Error { payload: ErrorPayload },
Terminate { payload: EmptyPayload },
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct SpawnRequest {
pub command: Vec<String>,
pub cwd: PathBuf,
pub env: HashMap<String, String>,
pub permission_profile: PermissionProfile,
pub workspace_roots: Vec<AbsolutePathBuf>,
pub codex_home: PathBuf,
pub real_codex_home: PathBuf,
pub cap_sids: Vec<String>,
#[serde(default)]
pub network_proxy_restricting_sid: Option<String>,
pub timeout_ms: Option<u64>,
pub tty: bool,
#[serde(default)]
pub stdin_open: bool,
#[serde(default)]
pub use_private_desktop: bool,
}源码位置:codex-rs/windows-sandbox-rs/src/elevated/runner_client.rs :: RunnerTransport::send_spawn_request、RunnerTransport::read_spawn_ready
pub(crate) fn send_spawn_request(&mut self, request: SpawnRequest) -> Result<()> {
let spawn_request = FramedMessage {
version: IPC_PROTOCOL_VERSION,
message: Message::SpawnRequest {
payload: Box::new(request),
},
};
write_frame(&mut self.pipe_write, &spawn_request)
}
pub(crate) fn read_spawn_ready(&mut self) -> Result<()> {
wait_for_complete_frame(&self.pipe_read, RUNNER_SPAWN_READY_TIMEOUT)?;
let msg = read_frame(&mut self.pipe_read)?
.ok_or_else(|| anyhow::anyhow!("runner pipe closed before spawn_ready"))?;
match msg.message {
Message::SpawnReady { .. } => Ok(()),
Message::Error { payload } => Err(RunnerStartupError::new(payload).into()),
other => Err(anyhow::anyhow!(
"expected spawn_ready from runner, got {other:?}"
)),
}
}帧协议把错误阶段区分为 ReadSpawnRequest、SpawnChild 和 WriteSpawnReady,因此父进程可以知道失败发生在 runner 读请求、创建子进程还是回写确认,而不是把所有错误归为“sandbox denied”。
8. 凭据刷新重试
elevated runner 启动失败不等于任意失败都可重试。retry_runner_spawn_once 只在 logon failure、no-such-logon-session,或 runner 的 SpawnChild 阶段出现可刷新错误码时刷新 sandbox credentials;WindowsApps 命令的特定错误不会因轮换密码而改善。刷新后使用原始统一 spawn request 再尝试一次。
源码位置:codex-rs/windows-sandbox-rs/src/elevated/runner_client.rs :: is_refreshable_sandbox_creds_error、retry_runner_spawn_once
pub(crate) fn retry_runner_spawn_once<T>(
sandbox_creds: SandboxCreds,
command: &[String],
mut spawn: impl FnMut(SandboxCreds) -> Result<T>,
refresh: impl FnOnce() -> Result<SandboxCreds>,
) -> Result<T> {
match spawn(sandbox_creds) {
Ok(result) => Ok(result),
Err(err) if is_refreshable_sandbox_creds_error(&err, command) => spawn(refresh()?),
Err(err) => Err(err),
}
}这条规则很窄:它只恢复可证明与 sandbox account 生命周期相关的错误,不会把 ACL、命令参数、权限不可表达或用户程序退出错误重新执行。
9. 网络与桌面
managed network 的代理身份通过 network_proxy_restricting_sid 传到 runner,并与 proxy_ports、allow_local_binding 一起参与 setup。unelevated backend 在 session 入口直接拒绝 proxy_enforced 或 restricting SID;否则网络控制所需的 firewall/SID 可能无法建立。private desktop 是独立的 spawn 参数,同时传给 legacy token/ConPTY 和 elevated runner。
源码位置:codex-rs/windows-sandbox-rs/src/unified_exec/mod.rs :: spawn_windows_sandbox_session_for_level
pub async fn spawn_windows_sandbox_session_for_level(
request: WindowsSandboxSessionRequest<'_>,
) -> Result<SpawnedProcess> {
if matches!(request.windows_sandbox_level, WindowsSandboxLevel::Elevated) {
backends::elevated::spawn_windows_sandbox_session_elevated_for_permission_profile(
request.permission_profile,
request.workspace_roots,
request.codex_home,
request.command,
request.cwd,
request.env_map,
request.proxy_enforced,
request.network_proxy_restricting_sid,
request.proxy_settings_mode,
request.timeout_ms,
request.read_roots_override,
request.read_roots_include_platform_defaults,
request.write_roots_override,
request.deny_read_paths_override,
request.deny_write_paths_override,
request.tty,
request.stdin_open,
request.use_private_desktop,
)
.await
} else {
if request.proxy_enforced {
bail!("managed networking requires the elevated Windows sandbox backend");
}
if request.network_proxy_restricting_sid.is_some() {
bail!("network proxy restricting SID requires the elevated Windows sandbox backend");
}
spawn_windows_sandbox_session_legacy(
request.permission_profile,
request.workspace_roots,
request.codex_home,
request.command,
request.cwd,
request.env_map,
request.timeout_ms,
request.deny_read_paths_override,
request.deny_write_paths_override,
request.tty,
request.stdin_open,
request.use_private_desktop,
)
.await
}
}10. 测试与证明边界
源码测试把“可在任何 target 检查的决策”和“必须 Windows 执行的系统效果”分开。Core 测试覆盖显式/历史 feature 到等级的映射、private desktop 默认值和代理端口提取;Windows sandbox 测试覆盖 managed network 在 restricted token 下的前置拒绝、deny-read 需要 elevated、runner request 序列化以及 credential refresh 的一次重试;真正的 token、ACL、Job Object、ConPTY 和 helper IPC 运行测试带有 Windows 条件。
源码位置:codex-rs/core/src/windows_sandbox_tests.rs :: elevated_wins_when_both_flags_are_enabled、resolve_windows_sandbox_private_desktop_defaults_to_true
#[test]
fn elevated_wins_when_both_flags_are_enabled() {
let mut features = Features::with_defaults();
features.enable(Feature::WindowsSandbox);
features.enable(Feature::WindowsSandboxElevated);
assert_eq!(
WindowsSandboxLevel::from_features(&features),
WindowsSandboxLevel::Elevated
);
}
#[test]
fn resolve_windows_sandbox_private_desktop_defaults_to_true() {
assert!(resolve_windows_sandbox_private_desktop(
&ConfigToml::default()
));
}源码位置:codex-rs/windows-sandbox-rs/src/unified_exec/tests.rs :: restricted_token_rejects_managed_network_before_spawn
.await
.expect_err("managed networking must fail before spawning an unelevated sandbox");
assert_eq!(
error.to_string(),
"managed networking requires the elevated Windows sandbox backend"
);输入、断言和边界分别是:给定两个启用 feature,等级断言必须是 elevated;给定缺失显式配置,private desktop 断言默认为 true;给定 restricted token + managed network,断言在创建进程前失败。它们能证明选择与拒绝时机,不能证明 Windows 内核实际应用了 token、ACL、firewall 或 Job Object。
在 Windows target 上可进一步运行:
cd codex-rs
cargo test -p codex-windows-sandbox --lib
cargo test -p codex-core windows_sandbox当前非 Windows 主机只能执行不依赖 Windows API 的配置、解析和序列化测试;不能把未运行的系统测试记为通过。
11. 阅读闭环
建议沿着 core/windows_sandbox.rs 的等级解析开始,进入 sandboxing/src/windows.rs 的可表达性检查,再看 sandboxing/src/spawn.rs 如何冻结请求字段。之后分别阅读 legacy 的 token/ACL/Job Object 和 elevated 的 setup/payload/runner IPC,最后回到 Core 的 timeout、cancel、output 收口。这样可以清楚区分三件容易混淆的事:权限快照如何形成、哪个进程真正执行命令、哪个句柄负责把进程树收干净。
下一篇深入 Windows 可读路径授权和 deny-read glob 的具体解析。
