pub fn whitelist_env_args(parent_env: &[(String, String)]) -> Vec { let mut args = vec!["--clearenv".to_string()]; for (key, value) in parent_env { if whitelist_keeps(key) { args.push("--setenv".to_string()); args.push(key.clone()); args.push(value.clone()); } } args } fn whitelist_keeps(key: &str) -> bool { WHITELIST_KEEP_EXACT.contains(&key) || WHITELIST_KEEP_PREFIXES .iter() .any(|prefix| key.starts_with(prefix)) } const WHITELIST_KEEP_EXACT: &[&str] = &[ // identity / shell "HOME", "USER", "LOGNAME", "PATH", "SHELL", // terminal "TERM", "COLORTERM", "NO_COLOR", "FORCE_COLOR", "CLICOLOR", // locale "LANG", "TZ", // editor "EDITOR", "VISUAL", "PAGER", // tmp "TMPDIR", // proxy "HTTP_PROXY", "HTTPS_PROXY", "NO_PROXY", "ALL_PROXY", "http_proxy", "https_proxy", "no_proxy", "all_proxy", // non-GUI XDG base dirs "XDG_CONFIG_HOME", "XDG_DATA_HOME", "XDG_CACHE_HOME", "XDG_STATE_HOME", "XDG_CONFIG_DIRS", "XDG_DATA_DIRS", ]; const WHITELIST_KEEP_PREFIXES: &[&str] = &[ "LC_", "ANTHROPIC_", "CLAUDE_", "CLAUDECODE", "OPENAI_", "CODEX_", "GEMINI_", "OTEL_", ]; pub fn blacklist_env_args(parent_env: &[(String, String)]) -> Vec { let mut args = Vec::new(); for (key, _) in parent_env { if blacklist_drops(key) { args.push("--unsetenv".to_string()); args.push(key.clone()); } } args } fn blacklist_drops(key: &str) -> bool { if BLACKLIST_KEEP_PREFIXES .iter() .any(|prefix| key.starts_with(prefix)) { return false; } if BLACKLIST_DROP_EXACT.contains(&key) { return true; } BLACKLIST_DROP_SUFFIXES .iter() .any(|suffix| key.ends_with(suffix)) } const BLACKLIST_KEEP_PREFIXES: &[&str] = &["ANTHROPIC_", "CLAUDE_", "OPENAI_", "CODEX_", "GEMINI_"]; const BLACKLIST_DROP_EXACT: &[&str] = &[ // dangling sockets after path overlays "DISPLAY", "WAYLAND_DISPLAY", "XAUTHORITY", "ICEAUTHORITY", "SESSION_MANAGER", "SSH_AUTH_SOCK", "SSH_AGENT_PID", "GPG_AGENT_INFO", "GPG_TTY", "GNUPGHOME", // cloud creds (don't fit suffix patterns) "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN", "AWS_SECURITY_TOKEN", "AWS_PROFILE", "GOOGLE_APPLICATION_CREDENTIALS", "AZURE_CLIENT_ID", "AZURE_TENANT_ID", // backups "RESTIC_PASSWORD_COMMAND", "RESTIC_PASSWORD_FILE", "RESTIC_KEY_HINT", "BORG_PASSPHRASE", "BORG_PASSCOMMAND", ]; const BLACKLIST_DROP_SUFFIXES: &[&str] = &[ "_TOKEN", "_SECRET", "_PASSWORD", "_PASSPHRASE", "_API_KEY", "_PRIVATE_KEY", "_CLIENT_SECRET", ];