From a2beb25d6ad0e1dc1dac1c2d3ebdbba117eb27f1 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 13 Oct 2026 14:58:54 +0000 Subject: [PATCH 1/3] Start fix for #823 (slice 10) Assisted-by: Claude Code:claude-opus-5-5 From d2a1385b38db9394e251f2350ee4aabc0896a7b0 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 13 Oct 2026 15:21:35 +0000 Subject: [PATCH 2/3] Spawn vlt test children through hermetic builder The vlt e2e, hosted and vendor test helpers each started socket-patch with a bare Command::new and their own SOCKET_* sweep. Those copies had drifted from tests/common/hermetic.rs: none removed flag-bound vars set in-process after the sweep, none used the hostile seeds that catch a dropped scrub, and the hosted helper left an ambient SOCKET_TELEMETRY_DISABLED=0 in place. All three now build on hermetic::command and keep only their own vlt and proxy scrubs. They leave PENDING_RAW_SPAWNS, so the ratchet keeps them hermetic. Refs #823 Assisted-by: Claude Code:claude-opus-5-5 --- .../tests/spawn_env_hygiene.rs | 3 -- .../tests/vlt_e2e_common/mod.rs | 12 ++++---- .../tests/vlt_hosted_common/mod.rs | 27 ++++++------------ .../tests/vlt_vendor_common/mod.rs | 28 ++++++------------- 4 files changed, 21 insertions(+), 49 deletions(-) diff --git a/crates/socket-patch-cli/tests/spawn_env_hygiene.rs b/crates/socket-patch-cli/tests/spawn_env_hygiene.rs index 70169605b..31fc8d684 100644 --- a/crates/socket-patch-cli/tests/spawn_env_hygiene.rs +++ b/crates/socket-patch-cli/tests/spawn_env_hygiene.rs @@ -68,9 +68,6 @@ const PENDING_RAW_SPAWNS: &[&str] = &[ "vex_e2e_common/uv.rs", "vex_pdm_hatch_common/mod.rs", "vex_pipenv_pip_common/mod.rs", - "vlt_e2e_common/mod.rs", - "vlt_hosted_common/mod.rs", - "vlt_vendor_common/mod.rs", ]; /// The environment `cmd`'s child would see: the parent environment with diff --git a/crates/socket-patch-cli/tests/vlt_e2e_common/mod.rs b/crates/socket-patch-cli/tests/vlt_e2e_common/mod.rs index b746664d5..ab892042d 100644 --- a/crates/socket-patch-cli/tests/vlt_e2e_common/mod.rs +++ b/crates/socket-patch-cli/tests/vlt_e2e_common/mod.rs @@ -1758,24 +1758,22 @@ pub fn urlencode(s: &str) -> String { // ── socket-patch ────────────────────────────────────────────────────────── -/// The socket-patch binary with the ambient `SOCKET_*`, `VLT_*`, npm and -/// proxy environment scrubbed. +/// The socket-patch binary with the hermetic `SOCKET_*` environment (see +/// `common::hermetic::command`) and the ambient `VLT_*`, npm and proxy +/// environment scrubbed. pub fn socket_cmd() -> Command { - let mut cmd = Command::new(socket_bin()); + let mut cmd = common::hermetic::command(&socket_bin()); cache_env::scrub_ambient_vlt_env(&mut cmd); for (key, _) in std::env::vars_os() { let name = key.to_string_lossy(); if ["http_proxy", "https_proxy", "all_proxy", "no_proxy"] .iter() .any(|p| name.eq_ignore_ascii_case(p)) - || name.starts_with("SOCKET_PATCH_VLT_E2E_") { cmd.env_remove(&key); } } - cmd.env("SOCKET_NO_CONFIG", "1") - .env("SOCKET_NO_UPDATE_CHECK", "1") - .env("SOCKET_TELEMETRY_DISABLED", "1") + cmd.envs(common::hermetic::FORCED_OPT_OUTS.iter().copied()) .env("VLT_TELEMETRY", "0") .env("LANG", "C") .env("LC_ALL", "C"); diff --git a/crates/socket-patch-cli/tests/vlt_hosted_common/mod.rs b/crates/socket-patch-cli/tests/vlt_hosted_common/mod.rs index 3693bb401..458839ce6 100644 --- a/crates/socket-patch-cli/tests/vlt_hosted_common/mod.rs +++ b/crates/socket-patch-cli/tests/vlt_hosted_common/mod.rs @@ -91,6 +91,8 @@ pub fn with_flags(line: &str, flags: u8) -> String { line.replacen("[0,", &format!("[{flags},"), 1) } +#[path = "../common/hermetic.rs"] +mod hermetic; #[path = "../common/oracle.rs"] mod oracle; @@ -418,32 +420,19 @@ pub fn ledger_path(root: &Path) -> PathBuf { root.join(".socket/vendor/redirect-state.json") } -/// The `socket-patch` binary with the ambient `SOCKET_*` and proxy -/// environment scrubbed (telemetry opt-outs kept). +/// The `socket-patch` binary with the hermetic `SOCKET_*` environment (see +/// `hermetic::command`) and the ambient proxy environment scrubbed. pub fn scrubbed_cli() -> std::process::Command { - let mut cmd = std::process::Command::new(env!("CARGO_BIN_EXE_socket-patch")); - cmd.env("SOCKET_DRY_RUN", "true") - .env("SOCKET_OFFLINE", "true") - .env("SOCKET_NO_VLT_INSTALL_CLEANUP", "true") - .env_remove("SOCKET_DRY_RUN") - .env_remove("SOCKET_OFFLINE") - .env_remove("SOCKET_NO_VLT_INSTALL_CLEANUP"); + let mut cmd = hermetic::binary_command(); for (key, _) in std::env::vars_os() { let name = key.to_string_lossy(); - let proxy = name.eq_ignore_ascii_case("http_proxy") - || name.eq_ignore_ascii_case("https_proxy") - || name.eq_ignore_ascii_case("all_proxy") - || name.eq_ignore_ascii_case("no_proxy"); - if proxy - || (name.starts_with("SOCKET_") - && !name.contains("TELEMETRY") - && name != "SOCKET_NO_CONFIG") + if ["http_proxy", "https_proxy", "all_proxy", "no_proxy"] + .iter() + .any(|p| name.eq_ignore_ascii_case(p)) { cmd.env_remove(&key); } } - cmd.env("SOCKET_NO_CONFIG", "1") - .env("SOCKET_NO_UPDATE_CHECK", "1"); cmd } diff --git a/crates/socket-patch-cli/tests/vlt_vendor_common/mod.rs b/crates/socket-patch-cli/tests/vlt_vendor_common/mod.rs index 4de6e0add..a178f1db4 100644 --- a/crates/socket-patch-cli/tests/vlt_vendor_common/mod.rs +++ b/crates/socket-patch-cli/tests/vlt_vendor_common/mod.rs @@ -18,6 +18,8 @@ #![allow(dead_code)] +#[path = "../common/hermetic.rs"] +mod hermetic; #[path = "../prebuilt_common/mod.rs"] mod prebuilt_common; @@ -347,34 +349,20 @@ pub fn capture_project(root: &Path, case: &Case) { // ── CLI ────────────────────────────────────────────────────────────────── -/// The `socket-patch` binary with the ambient `SOCKET_*`, `VLT_*` and proxy -/// environment scrubbed (telemetry disabled). +/// The `socket-patch` binary with the hermetic `SOCKET_*` environment (see +/// `hermetic::command`) and the ambient `VLT_*` and proxy environment +/// scrubbed. pub fn cli() -> Command { - let mut cmd = Command::new(env!("CARGO_BIN_EXE_socket-patch")); + let mut cmd = hermetic::binary_command(); for (key, _) in std::env::vars_os() { - let name = key.to_string_lossy().to_string(); + let name = key.to_string_lossy(); let proxy = ["http_proxy", "https_proxy", "all_proxy", "no_proxy"] .iter() .any(|p| name.eq_ignore_ascii_case(p)); - if proxy - || name.starts_with("VLT_") - || (name.starts_with("SOCKET_") && name != "SOCKET_NO_CONFIG") - { + if proxy || name.starts_with("VLT_") { cmd.env_remove(&key); } } - for key in [ - "SOCKET_OFFLINE", - "SOCKET_DRY_RUN", - "SOCKET_API_URL", - "SOCKET_PROXY_URL", - "SOCKET_NO_VLT_INSTALL_CLEANUP", - ] { - cmd.env_remove(key); - } - cmd.env("SOCKET_TELEMETRY_DISABLED", "1") - .env("SOCKET_NO_CONFIG", "1") - .env("SOCKET_NO_UPDATE_CHECK", "1"); cmd } From 9fed1567eb82352d80bc3a65e822f81c8b188383 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 13 Oct 2026 15:31:50 +0000 Subject: [PATCH 3/3] Keep test opt-outs after the vlt env scrub The shared vlt scrub also removes SOCKET_* vars, so running it on a socket-patch child built by the hermetic builder would turn telemetry and the update check back on. Add a vlt scrub that leaves SOCKET_* to the builder, as the bun suites already have, and use it for the vlt e2e CLI child instead of re-applying the opt-outs by hand. Refs #823 Assisted-by: Claude Code:claude-opus-5-5 --- .../tests/common/cache_env.rs | 35 +++++++++++++++++-- .../tests/vlt_e2e_common/mod.rs | 5 ++- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/crates/socket-patch-cli/tests/common/cache_env.rs b/crates/socket-patch-cli/tests/common/cache_env.rs index cde80a5e1..020b69d75 100644 --- a/crates/socket-patch-cli/tests/common/cache_env.rs +++ b/crates/socket-patch-cli/tests/common/cache_env.rs @@ -318,8 +318,9 @@ fn scrub_parent_vars(cmd: &mut Command, parent: Vec, ambient: fn(&str) // ── Ambient-env scrub for the vlt suites ────────────────────────────── -/// True for an ambient variable the real-vlt suites strip from every child -/// (vlt and the CLI under test) before [`isolate`]: +/// True for an ambient variable the real-vlt suites strip from every vlt +/// child before [`isolate`] (a `socket-patch` child built with +/// `hermetic::command` takes [`scrub_ambient_vlt_tool_env`] instead): /// /// * every `VLT_*` — vlt reads each config option from `VLT_