kz-proxy 0.3.0

MITM proxy and subprocess sandbox for blind secret injection
Documentation
//! Run child process with proxy environment variables.

use std::path::Path;

/// Essential OS vars to preserve from the parent environment in blind mode.
pub const ESSENTIAL_VARS: &[&str] = &[
    "PATH", "HOME", "USER", "SHELL", "TERM", "LANG", "LC_ALL", "TMPDIR", "TZ",
];

/// Run child process with proxy env vars set (HTTP_PROXY, HTTPS_PROXY, SSL_CERT_FILE, etc.).
///
/// The parent environment is cleared first so that real secret values from the
/// parent shell are never inherited by the subprocess. Only essential OS vars,
/// proxy vars, and the masked secret vars are injected.
pub(crate) fn run_child(
    program: &str,
    args: &[String],
    proxy_url: &str,
    env_vars_with_masked: &[(String, String)],
    ssl_cert_file: &Path,
) -> Result<std::process::ExitStatus, Box<dyn std::error::Error + Send + Sync>> {
    let mut command = std::process::Command::new(program);
    command.args(args);

    // Clear the entire parent environment so real secrets are never inherited
    command.env_clear();

    // Re-inject essential OS vars from the parent
    for &var in ESSENTIAL_VARS {
        if let Ok(val) = std::env::var(var) {
            command.env(var, val);
        }
    }

    // Set proxy vars
    command.env("HTTP_PROXY", proxy_url);
    command.env("HTTPS_PROXY", proxy_url);
    command.env("NO_PROXY", "");
    let ssl_path = ssl_cert_file.to_string_lossy();
    command.env("SSL_CERT_FILE", ssl_path.as_ref());
    command.env("NODE_EXTRA_CA_CERTS", ssl_path.as_ref());
    command.env("REQUESTS_CA_BUNDLE", ssl_path.as_ref());

    // Inject masked secret values (not the real ones)
    for (k, v) in env_vars_with_masked {
        command.env(k, v);
    }

    let status = command
        .status()
        .map_err(|e| -> Box<dyn std::error::Error + Send + Sync> { e.into() })?;
    Ok(status)
}