Prevent launch context from reaching child processes (#37607)

## Why

Model-reachable child processes should not inherit Codex launch context.

## What changed

- Treat `OPENAI_FEDERATION_RULE_ID` and `OPENAI_IDENTITY_TOKEN_FILE` as non-inheritable environment variables, with case-insensitive matching.
- Remove them after shell environment policy overrides and before spawning commands across execution, MCP, hooks, Git helpers, and remote helper processes.

## Testing

- Cover inherited and explicitly configured variants, including mixed-case names.
- Verify the variables are absent from real child environments and app-server command and process execution.

GitOrigin-RevId: 2535527893985fef0995617f4c5b2462bea7c136
This commit is contained in:
cooper-oai
2026-08-08 16:51:07 +00:00
committed by copyberry
parent 3aae5d885b
commit c4513cb982
25 changed files with 269 additions and 36 deletions

View File

@@ -11,6 +11,7 @@ use tracing::debug;
use tracing::warn;
use codex_http_client::HttpClientFactory;
use codex_protocol::shell_environment::scrub_non_inheritable_env_vars;
use codex_utils_rustls_provider::ensure_rustls_crypto_provider;
use codex_websocket_client::WebSocketConnector;
use codex_websocket_client::WebSocketTlsMode;
@@ -441,6 +442,7 @@ fn stdio_command_process(stdio_command: &StdioExecServerCommand) -> Command {
let mut command = Command::new(&stdio_command.program);
command.args(&stdio_command.args);
command.envs(&stdio_command.env);
scrub_non_inheritable_env_vars(command.as_std_mut());
if let Some(cwd) = &stdio_command.cwd {
command.current_dir(cwd);
}

View File

@@ -327,7 +327,7 @@ fn spawn_command(
SandboxExecRequest {
command: argv,
cwd,
env,
mut env,
arg0,
..
}: SandboxExecRequest,
@@ -346,6 +346,7 @@ fn spawn_command(
// TODO(anp): Keep PathUri through the filesystem helper launch boundary.
let cwd = cwd.to_abs_path().map_err(io_error)?;
command.current_dir(cwd.as_path());
env.retain(|name, _| !codex_protocol::shell_environment::is_non_inheritable_env_var(name));
command.env_clear();
command.envs(env);
command.stdin(std::process::Stdio::piped());

View File

@@ -649,6 +649,7 @@ fn child_env(params: &ExecParams) -> HashMap<String, String> {
None => params.env.clone(),
};
env.remove(crate::CODEX_EXEC_SERVER_EXIT_ON_STDIN_CLOSE_ENV_VAR);
env.retain(|name, _| !shell_environment::is_non_inheritable_env_var(name));
env
}
@@ -1268,12 +1269,19 @@ mod tests {
let mut params = test_exec_params(HashMap::from([
("OVERLAY".to_string(), "overlay".to_string()),
("POLICY_SET".to_string(), "overlay-wins".to_string()),
(
"openai_identity_token_file".to_string(),
"/run/identity-token".to_string(),
),
]));
params.env_policy = Some(ExecEnvPolicy {
inherit: ShellEnvironmentPolicyInherit::None,
ignore_default_excludes: true,
exclude: Vec::new(),
r#set: HashMap::from([("POLICY_SET".to_string(), "policy".to_string())]),
r#set: HashMap::from([
("POLICY_SET".to_string(), "policy".to_string()),
("OpenAI_Federation_Rule_Id".to_string(), "rule".to_string()),
]),
include_only: Vec::new(),
});