Load cloud config for sandbox and remote exec-server commands (#57270)

## Why

Sandbox invocations without an explicit permissions profile and remote `exec-server` connections using ChatGPT auth need access to cloud-defined model providers and managed requirements. Cloud bootstrap requests must also respect local application network policy.

## What changed

- Bootstrap sandbox cloud config whenever managed config is included, even without an explicit profile. Skip bootstrap when `--sandbox-state-json` supplies the sandbox state.
- Load cloud config for remote executors beyond workload identity, while skipping forwarders and executors using stdin credentials, AWS SigV4, or agent identity auth. Honor `CODEX_API_KEY` selection so API key connections skip ChatGPT cloud config.
- Apply local application network policy during cloud bootstrap and activate effective application network policy before exec-server clients are created.

## Testing

Add coverage for cloud-defined providers in sandbox and remote exec-server invocations, API key bypass, local policy blocking bundle requests, cloud policy blocking remote registration, and bootstrap exclusions.

GitOrigin-RevId: e8bd6210751e96161f575ade309ebf41bf10f8b5
This commit is contained in:
Abhinav
2026-10-26 21:31:28 +00:00
committed by copyberry
parent 0818b91867
commit 51e3f94b2b
7 changed files with 273 additions and 79 deletions
@@ -1,3 +1,4 @@
use codex_app_server::in_process::EmbeddedNetworkPolicy;
use codex_cloud_config::chatgpt_config_bundle_loader_for_storage;
use codex_config::CloudConfigBundleLoader;
use codex_config::ConfigLoadOptions;
@@ -15,7 +16,7 @@ pub(super) async fn bootstrap_cloud_config_bundle(
resolve_codex_home: impl FnOnce() -> std::io::Result<AbsolutePathBuf>,
strict_config: bool,
) -> anyhow::Result<CloudConfigBundleLoader> {
if options.permissions_profile.is_none()
if options.sandbox_state.sandbox_state_json.is_some()
|| !matches!(
options.managed_requirements_mode,
ManagedRequirementsMode::Include
@@ -29,6 +30,7 @@ pub(super) async fn bootstrap_cloud_config_bundle(
Some(cwd) => AbsolutePathBuf::relative_to_current_dir(cwd)?,
None => AbsolutePathBuf::current_dir()?,
};
let network_policy = EmbeddedNetworkPolicy::load(&options.loader_overrides).await;
let bootstrap_config = load_config_toml_with_layer_stack(
codex_home.as_path(),
Some(&cwd),
@@ -41,7 +43,10 @@ pub(super) async fn bootstrap_cloud_config_bundle(
)
.await?;
Ok(chatgpt_config_bundle_loader_for_storage(
bootstrap_auth_config(codex_home.as_path(), &bootstrap_config)?,
network_policy.bind_bootstrap_auth(bootstrap_auth_config(
codex_home.as_path(),
&bootstrap_config,
)?),
/*enable_codex_api_key_env*/ false,
)
.await?)