Allow full-access Windows setup to provision through registered Core (#47922)

## Why

Elevated Windows sandbox setup rejected `danger-full-access` as an incompatible permission profile before registered Core could reach the provisioning service.

## What changed

Allow `PermissionProfile::Disabled` to reach service provisioning when registered Core is requested. Keep legacy full-access setup on the shared setup path and retain permission validation before provisioning for restricted profiles.

## Testing

Add Windows-only regression cases covering full-access and supported restricted profiles reaching the service, unsupported restricted permissions failing before provisioning, and legacy full-access setup skipping the service. Each case checks the completion error and verifies that the configuration file remains unchanged.

GitOrigin-RevId: 5ba190da6f8b1c6ef665015acdb9428718a724dc
This commit is contained in:
zm-oai
2026-09-24 19:29:53 +00:00
committed by copyberry
parent c19dcd975d
commit 731d4a5ca8
2 changed files with 123 additions and 12 deletions
@@ -192,19 +192,30 @@ impl WindowsSandboxRequestProcessor {
let service_setup_request = setup_request.clone();
let service_setup_start = Instant::now();
tokio::task::spawn_blocking(move || -> anyhow::Result<()> {
let Ok(permissions) = codex_windows_sandbox::ResolvedWindowsSandboxPermissions::try_from_permission_profile_for_workspace_roots(
if matches!(
&service_setup_request.permission_profile,
&service_setup_request.workspace_roots,
) else {
anyhow::ensure!(!codex_windows_sandbox::registered_core_requested(),
"registered Core requires a service-compatible sandbox policy");
// The existing setup path can still succeed for completed
// provisioning without resolving the current profile.
return Ok(());
};
permissions.validate_elevated_filesystem_policy(
&service_setup_request.command_cwd,
)?;
codex_protocol::models::PermissionProfile::Disabled
) {
// Only registered Core needs service provisioning for full access;
// legacy setup keeps using the shared setup path below.
if !codex_windows_sandbox::registered_core_requested() {
return Ok(());
}
} else {
let Ok(permissions) = codex_windows_sandbox::ResolvedWindowsSandboxPermissions::try_from_permission_profile_for_workspace_roots(
&service_setup_request.permission_profile,
&service_setup_request.workspace_roots,
) else {
anyhow::ensure!(!codex_windows_sandbox::registered_core_requested(),
"registered Core requires a service-compatible sandbox policy");
// The existing setup path can still succeed for completed
// provisioning without resolving the current profile.
return Ok(());
};
permissions.validate_elevated_filesystem_policy(
&service_setup_request.command_cwd,
)?;
}
// The shared setup path below handles helper fallback and
// refreshes workspace ACLs after provisioning.
codex_windows_sandbox::provision_windows_sandbox_via_service(
@@ -112,6 +112,106 @@ async fn windows_sandbox_setup_start_emits_completion_notification() -> Result<(
Ok(())
}
#[cfg(target_os = "windows")]
#[test_case::test_case(
"sandbox_mode = 'danger-full-access'",
true,
"app runtime provisioning service is unavailable; refusing helper fallback";
"full access reaches the service"
)]
#[test_case::test_case(
"sandbox_mode = 'workspace-write'",
true,
"app runtime provisioning service is unavailable; refusing helper fallback";
"supported restricted permissions reach the service"
)]
#[test_case::test_case(
"default_permissions = 'workspace'\n[permissions.workspace.filesystem]\n':workspace_roots' = 'write'",
true,
"elevated Windows sandbox requires effective `:root` read access";
"unsupported restricted permissions fail before the service"
)]
#[test_case::test_case(
"sandbox_mode = 'danger-full-access'\n[features]\nwindows_sandbox_service = true",
false,
"only managed permission profiles can be enforced by the Windows sandbox";
"legacy full access skips the service and reaches shared setup"
)]
#[tokio::test]
async fn setup_validates_permissions_before_provisioning(
config: &str,
registered_core: bool,
expected_error: &str,
) -> Result<()> {
let codex_home = TempDir::new()?;
let config_path = codex_home.path().join("config.toml");
std::fs::write(&config_path, config)?;
// Registered tests use a nonexistent service; an invalid hint detects any legacy service call.
let service_family = if registered_core {
format!(
"CodexSetupTest{}_0000000000000",
uuid::Uuid::now_v7().simple()
)
} else {
"invalid-service-family".into()
};
let mut mcp = TestAppServer::builder()
.with_codex_home(codex_home.path())
.without_auto_env()
.without_managed_config()
.with_env_overrides(&[
(
"CODEX_WINDOWS_REGISTERED_CORE",
Some(if registered_core { "1" } else { "0" }),
),
(
"CODEX_WINDOWS_SANDBOX_PACKAGE_FAMILY",
Some(&service_family),
),
(
codex_protocol::shell_environment::OPENAI_FEDERATION_RULE_ID_ENV_VAR,
None,
),
(
codex_protocol::shell_environment::OPENAI_IDENTITY_TOKEN_FILE_ENV_VAR,
None,
),
])
.build_initialized_with_timeout(DEFAULT_READ_TIMEOUT)
.await?;
let request_id = mcp
.send_windows_sandbox_setup_start_request(WindowsSandboxSetupStartParams {
mode: WindowsSandboxSetupMode::Elevated,
cwd: None,
})
.await?;
let response: WindowsSandboxSetupStartResponse =
timeout(DEFAULT_READ_TIMEOUT, mcp.read_response(request_id)).await??;
assert_eq!(response, WindowsSandboxSetupStartResponse { started: true });
let notification = timeout(
DEFAULT_READ_TIMEOUT,
mcp.read_stream_until_notification_message("windowsSandbox/setupCompleted"),
)
.await??;
let completion: WindowsSandboxSetupCompletedNotification = serde_json::from_value(
notification
.params
.context("missing setup completion params")?,
)?;
assert_eq!(
completion,
WindowsSandboxSetupCompletedNotification {
mode: WindowsSandboxSetupMode::Elevated,
success: false,
error: Some(expected_error.into()),
}
);
assert_eq!(std::fs::read_to_string(config_path)?, config);
Ok(())
}
#[tokio::test]
async fn windows_sandbox_setup_start_rejects_relative_cwd() -> Result<()> {
let codex_home = TempDir::new()?;