Skip to main content

kz_proxy/
enforce.rs

1//! Run child process with proxy environment variables.
2
3use std::path::Path;
4
5/// Essential OS vars to preserve from the parent environment in blind mode.
6pub const ESSENTIAL_VARS: &[&str] = &[
7    "PATH", "HOME", "USER", "SHELL", "TERM", "LANG", "LC_ALL", "TMPDIR", "TZ",
8];
9
10/// Run child process with proxy env vars set (HTTP_PROXY, HTTPS_PROXY, SSL_CERT_FILE, etc.).
11///
12/// The parent environment is cleared first so that real secret values from the
13/// parent shell are never inherited by the subprocess. Only essential OS vars,
14/// proxy vars, and the masked secret vars are injected.
15pub(crate) fn run_child(
16    program: &str,
17    args: &[String],
18    proxy_url: &str,
19    env_vars_with_masked: &[(String, String)],
20    ssl_cert_file: &Path,
21) -> Result<std::process::ExitStatus, Box<dyn std::error::Error + Send + Sync>> {
22    let mut command = std::process::Command::new(program);
23    command.args(args);
24
25    // Clear the entire parent environment so real secrets are never inherited
26    command.env_clear();
27
28    // Re-inject essential OS vars from the parent
29    for &var in ESSENTIAL_VARS {
30        if let Ok(val) = std::env::var(var) {
31            command.env(var, val);
32        }
33    }
34
35    // Set proxy vars
36    command.env("HTTP_PROXY", proxy_url);
37    command.env("HTTPS_PROXY", proxy_url);
38    command.env("NO_PROXY", "");
39    let ssl_path = ssl_cert_file.to_string_lossy();
40    command.env("SSL_CERT_FILE", ssl_path.as_ref());
41    command.env("NODE_EXTRA_CA_CERTS", ssl_path.as_ref());
42    command.env("REQUESTS_CA_BUNDLE", ssl_path.as_ref());
43
44    // Inject masked secret values (not the real ones)
45    for (k, v) in env_vars_with_masked {
46        command.env(k, v);
47    }
48
49    let status = command
50        .status()
51        .map_err(|e| -> Box<dyn std::error::Error + Send + Sync> { e.into() })?;
52    Ok(status)
53}