Compare commits

...

1 Commits

Author SHA1 Message Date
David Wiesen
feb315a7aa windows-sandbox: sanitize elevated runner profile env 2026-05-01 10:13:07 -07:00
3 changed files with 86 additions and 3 deletions

View File

@@ -35,6 +35,7 @@ use codex_windows_sandbox::encode_bytes;
use codex_windows_sandbox::get_current_token_for_restriction;
use codex_windows_sandbox::hide_current_user_profile_dir;
use codex_windows_sandbox::log_note;
use codex_windows_sandbox::overlay_current_user_profile_env;
use codex_windows_sandbox::parse_policy;
use codex_windows_sandbox::read_frame;
use codex_windows_sandbox::read_handle_loop;
@@ -189,6 +190,8 @@ fn effective_cwd(req_cwd: &Path, log_dir: Option<&Path>) -> PathBuf {
fn spawn_ipc_process(req: &SpawnRequest) -> Result<IpcSpawnedProcess> {
let log_dir = req.codex_home.clone();
hide_current_user_profile_dir(req.codex_home.as_path());
let mut child_env = req.env.clone();
overlay_current_user_profile_env(&mut child_env);
let policy = parse_policy(&req.policy_json_or_preset).context("parse policy_json_or_preset")?;
let mut cap_psids: Vec<*mut c_void> = Vec::new();
for sid in &req.cap_sids {
@@ -241,7 +244,7 @@ fn spawn_ipc_process(req: &SpawnRequest) -> Result<IpcSpawnedProcess> {
h_token,
&req.command,
&effective_cwd,
&req.env,
&child_env,
req.use_private_desktop,
Some(log_dir.as_path()),
)?;
@@ -272,7 +275,7 @@ fn spawn_ipc_process(req: &SpawnRequest) -> Result<IpcSpawnedProcess> {
h_token,
&req.command,
&effective_cwd,
&req.env,
&child_env,
stdin_mode,
StderrMode::Separate,
req.use_private_desktop,

View File

@@ -1,4 +1,4 @@
use anyhow::{anyhow, Result};
use anyhow::{Result, anyhow};
use dirs_next::home_dir;
use std::collections::HashMap;
use std::env;
@@ -42,6 +42,36 @@ pub fn inherit_path_env(env_map: &mut HashMap<String, String>) {
}
}
const PROFILE_ENV_KEYS: &[&str] = &[
"USERPROFILE",
"HOME",
"HOMEDRIVE",
"HOMEPATH",
"APPDATA",
"LOCALAPPDATA",
"TEMP",
"TMP",
];
pub fn overlay_current_user_profile_env(env_map: &mut HashMap<String, String>) {
let current_env: HashMap<String, String> = PROFILE_ENV_KEYS
.iter()
.filter_map(|key| env::var(key).ok().map(|value| ((*key).to_string(), value)))
.collect();
overlay_profile_env_from(env_map, &current_env);
}
pub fn overlay_profile_env_from(
env_map: &mut HashMap<String, String>,
current_env: &HashMap<String, String>,
) {
for key in PROFILE_ENV_KEYS {
if let Some(value) = current_env.get(*key) {
env_map.insert((*key).to_string(), value.clone());
}
}
}
fn prepend_path(env_map: &mut HashMap<String, String>, prefix: &str) {
let existing = env_map
.get("PATH")
@@ -172,3 +202,51 @@ pub fn apply_no_network_to_env(env_map: &mut HashMap<String, String>) -> Result<
reorder_pathext_for_stubs(env_map);
Ok(())
}
#[cfg(test)]
mod tests {
use super::overlay_profile_env_from;
use std::collections::HashMap;
#[test]
fn overlay_profile_env_replaces_profile_sensitive_paths() {
let mut env_map = HashMap::from([
("USERPROFILE".to_string(), "C:\\Users\\host".to_string()),
(
"LOCALAPPDATA".to_string(),
"C:\\Users\\host\\AppData\\Local".to_string(),
),
("KEEP_ME".to_string(), "unchanged".to_string()),
]);
let current_env = HashMap::from([
(
"USERPROFILE".to_string(),
"C:\\Users\\CodexSandbox".to_string(),
),
(
"LOCALAPPDATA".to_string(),
"C:\\Users\\CodexSandbox\\AppData\\Local".to_string(),
),
(
"TEMP".to_string(),
"C:\\Users\\CodexSandbox\\AppData\\Local\\Temp".to_string(),
),
]);
overlay_profile_env_from(&mut env_map, &current_env);
assert_eq!(
env_map.get("USERPROFILE"),
Some(&"C:\\Users\\CodexSandbox".to_string())
);
assert_eq!(
env_map.get("LOCALAPPDATA"),
Some(&"C:\\Users\\CodexSandbox\\AppData\\Local".to_string())
);
assert_eq!(
env_map.get("TEMP"),
Some(&"C:\\Users\\CodexSandbox\\AppData\\Local\\Temp".to_string())
);
assert_eq!(env_map.get("KEEP_ME"), Some(&"unchanged".to_string()));
}
}

View File

@@ -107,6 +107,8 @@ pub use elevated_impl::ElevatedSandboxCaptureRequest;
#[cfg(target_os = "windows")]
pub use elevated_impl::run_windows_sandbox_capture as run_windows_sandbox_capture_elevated;
#[cfg(target_os = "windows")]
pub use env::overlay_current_user_profile_env;
#[cfg(target_os = "windows")]
pub use helper_materialization::resolve_current_exe_for_launch;
#[cfg(target_os = "windows")]
pub use hide_users::hide_current_user_profile_dir;