From a7a1d96e75d383f8eeca62ded9628a1e59dd4248 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 13 Oct 2026 13:55:13 +0000 Subject: [PATCH 1/4] Start fix for #823 (slice 9) Assisted-by: Claude Code:claude-opus-5-5 From b8b43bcfa396bf565aadba51050ff5f7383bf45b Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 13 Oct 2026 14:02:59 +0000 Subject: [PATCH 2/4] Spawn vendor build test children hermetically Ten vendor build suites started socket-patch with a bare Command::new and their own SOCKET_* sweep. The copies drifted: most kept an ambient SOCKET_NO_CONFIG (so SOCKET_NO_CONFIG=0 let a developer's real login authenticate the child), none forced the update notifier off, and the maven/jvm copies re-added the opt-outs by hand. Their run helpers now go through tests/common/hermetic.rs, and the files leave PENDING_RAW_SPAWNS (42 -> 32) so the ratchet keeps them hermetic. Suite-specific scrubs stay: VIRTUAL_ENV, M2_HOME, the bun tool vars (now the SOCKET_*-free scrub_ambient_bun_tool_env), and the gem suite now drops every ambient BUNDLE_* like the redirect suite. Refs #823. Assisted-by: Claude Code:claude-opus-5-5 --- .../tests/e2e_vendor_bun_build.rs | 11 +++++----- .../tests/e2e_vendor_cargo_build.rs | 15 +++++--------- .../tests/e2e_vendor_composer_build.rs | 20 ++++++++----------- .../tests/e2e_vendor_composer_crlf.rs | 13 ++++-------- .../tests/e2e_vendor_gem_build.rs | 19 ++++++++---------- .../tests/e2e_vendor_golang_build.rs | 16 ++++++--------- .../tests/e2e_vendor_jvm_build.rs | 15 ++++---------- .../tests/e2e_vendor_maven_build.rs | 12 ++--------- .../tests/e2e_vendor_npm_build.rs | 18 +++++++---------- .../tests/e2e_vendor_pypi_build.rs | 17 ++++++---------- .../tests/spawn_env_hygiene.rs | 10 ---------- 11 files changed, 56 insertions(+), 110 deletions(-) diff --git a/crates/socket-patch-cli/tests/e2e_vendor_bun_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_bun_build.rs index 28012eedd..3a2b01ccc 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_bun_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_bun_build.rs @@ -76,7 +76,7 @@ #[path = "common/mod.rs"] mod common; -use common::{binary, git_sha256, parse_json_envelope}; +use common::{binary, git_sha256, hermetic_command, parse_json_envelope}; #[path = "prebuilt_common/mod.rs"] mod prebuilt_common; @@ -279,12 +279,13 @@ fn bun(cwd: &Path, args: &[&str], cache_dir: &Path) -> Output { cmd.output().expect("failed to run bun") } -/// The real binary with `--no-telemetry` appended: nothing in this suite -/// should ever post a telemetry event, mocked API or not. +/// The real binary in the hermetic environment (`tests/common/hermetic.rs`) +/// plus the bun tool scrub, with `--no-telemetry` appended: nothing in this +/// suite should ever post a telemetry event, mocked API or not. fn run_socket(cwd: &Path, args: &[&str]) -> (i32, String, String) { - let mut cmd = Command::new(binary()); + let mut cmd = hermetic_command(&binary()); cmd.current_dir(cwd); - cache_env::scrub_ambient_bun_env(&mut cmd); + cache_env::scrub_ambient_bun_tool_env(&mut cmd); let _fixture = prebuilt_common::prepare_command(&mut cmd, cwd, args, &[]); cmd.arg("--no-telemetry"); let out = cmd.output().expect("failed to run socket-patch binary"); diff --git a/crates/socket-patch-cli/tests/e2e_vendor_cargo_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_cargo_build.rs index 92e909b32..cc46f245a 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_cargo_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_cargo_build.rs @@ -81,7 +81,7 @@ #[path = "common/mod.rs"] mod common; -use common::{binary, git_sha256, parse_json_envelope}; +use common::{binary, git_sha256, hermetic, hermetic_command, parse_json_envelope}; #[path = "prebuilt_common/mod.rs"] mod prebuilt_common; @@ -204,18 +204,13 @@ fn metadata_version(dir: &Path, cargo_home: &Path) -> String { // ── self-contained helpers ──────────────────────────────────────────── -/// Run socket-patch with ambient `SOCKET_*` vars scrubbed and the fixture's -/// private CARGO_HOME injected (the cargo crawler resolves the registry +/// Run socket-patch in the hermetic environment (`tests/common/hermetic.rs`) +/// with the fixture's private CARGO_HOME injected (the cargo crawler resolves the registry /// source tree through it). fn run_socket(cwd: &Path, args: &[&str], cargo_home: &Path) -> (i32, String, String) { - let mut cmd = Command::new(binary()); + let mut cmd = hermetic_command(&binary()); + hermetic::scrub_extra(&mut cmd, &[hermetic::Extra::Venv]); cmd.current_dir(cwd); - for (k, _) in std::env::vars_os() { - if k.to_string_lossy().starts_with("SOCKET_") && k.to_string_lossy() != "SOCKET_NO_CONFIG" { - cmd.env_remove(&k); - } - } - cmd.env_remove("VIRTUAL_ENV"); cmd.env("CARGO_HOME", cargo_home); let _fixture = prebuilt_common::prepare_command( &mut cmd, diff --git a/crates/socket-patch-cli/tests/e2e_vendor_composer_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_composer_build.rs index 371c94a57..a210e834d 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_composer_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_composer_build.rs @@ -60,13 +60,13 @@ #[path = "common/mod.rs"] mod common; -use common::{binary, git_sha256}; +use common::{binary, git_sha256, hermetic, hermetic_command}; #[path = "prebuilt_common/mod.rs"] mod prebuilt_common; use std::path::{Path, PathBuf}; -use std::process::{Command, Output}; +use std::process::Output; use wiremock::matchers::{method, path, path_regex}; use wiremock::{Mock, MockServer, ResponseTemplate}; @@ -96,18 +96,14 @@ const FIXTURE_VERSION: &str = "3.0.2"; // ── self-contained helpers ──────────────────────────────────────────── -/// Run the socket-patch binary with a scrubbed environment: every ambient -/// `SOCKET_*` var is removed (so a developer's `SOCKET_DRY_RUN=1` etc. can't -/// flip behavior) along with `VIRTUAL_ENV` (crawler discovery input). +/// Run the socket-patch binary in the hermetic environment +/// (`tests/common/hermetic.rs`: no ambient `SOCKET_*`, so a developer's +/// `SOCKET_DRY_RUN=1` etc. can't flip behavior) with `VIRTUAL_ENV` (crawler +/// discovery input) removed. fn run_socket(cwd: &Path, args: &[&str]) -> (i32, String, String) { - let mut cmd = Command::new(binary()); + let mut cmd = hermetic_command(&binary()); + hermetic::scrub_extra(&mut cmd, &[hermetic::Extra::Venv]); cmd.current_dir(cwd); - for (k, _) in std::env::vars_os() { - if k.to_string_lossy().starts_with("SOCKET_") && k.to_string_lossy() != "SOCKET_NO_CONFIG" { - cmd.env_remove(&k); - } - } - cmd.env_remove("VIRTUAL_ENV"); let _fixture = prebuilt_common::prepare_command(&mut cmd, cwd, args, &[]); let out = cmd.output().expect("failed to run socket-patch binary"); ( diff --git a/crates/socket-patch-cli/tests/e2e_vendor_composer_crlf.rs b/crates/socket-patch-cli/tests/e2e_vendor_composer_crlf.rs index d60b87408..f1d4992ed 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_composer_crlf.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_composer_crlf.rs @@ -8,6 +8,8 @@ //! the pre-vendor bytes exactly. Each test runs the built binary; the //! discovery/view routes are a wiremock API, so no composer and no network. +#[path = "common/hermetic.rs"] +mod hermetic; #[path = "prebuilt_common/mod.rs"] mod prebuilt_common; @@ -168,16 +170,9 @@ async fn mount_api(server: &MockServer) { .await; } +/// The built binary in the hermetic environment (`tests/common/hermetic.rs`). fn cli() -> Command { - let mut cmd = Command::new(env!("CARGO_BIN_EXE_socket-patch")); - for (key, _) in std::env::vars_os() { - let name = key.to_string_lossy(); - if name.starts_with("SOCKET_") && name != "SOCKET_NO_CONFIG" { - cmd.env_remove(&key); - } - } - cmd.env("SOCKET_TELEMETRY_DISABLED", "1"); - cmd + hermetic::binary_command() } fn run_json(root: &Path, args: &[&str]) -> (i32, Value) { diff --git a/crates/socket-patch-cli/tests/e2e_vendor_gem_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_gem_build.rs index e24906ee4..0098e4d40 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_gem_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_gem_build.rs @@ -60,7 +60,7 @@ #[path = "common/mod.rs"] mod common; -use common::{binary, git_sha256, parse_json_envelope}; +use common::{binary, git_sha256, hermetic, hermetic_command, parse_json_envelope}; #[path = "prebuilt_common/mod.rs"] mod prebuilt_common; @@ -102,18 +102,15 @@ fn argv(args: &[String]) -> Vec<&str> { args.iter().map(String::as_str).collect() } -/// Run the socket-patch binary with a scrubbed environment: every ambient -/// `SOCKET_*` var is removed (so a developer's `SOCKET_DRY_RUN=1` etc. can't -/// flip behavior) along with `VIRTUAL_ENV` (crawler discovery input). +/// Run the socket-patch binary in the hermetic environment +/// (`tests/common/hermetic.rs`: no ambient `SOCKET_*`, so a developer's +/// `SOCKET_DRY_RUN=1` etc. can't flip behavior) with `VIRTUAL_ENV` and every +/// `BUNDLE_*` (crawler discovery inputs: an ambient `BUNDLE_PATH` or +/// `BUNDLE_GEMFILE` would point the crawler away from the fixture) removed. fn run_socket(cwd: &Path, args: &[&str]) -> (i32, String, String) { - let mut cmd = Command::new(binary()); + let mut cmd = hermetic_command(&binary()); + hermetic::scrub_extra(&mut cmd, &[hermetic::Extra::Venv, hermetic::Extra::Bundle]); cmd.current_dir(cwd); - for (k, _) in std::env::vars_os() { - if k.to_string_lossy().starts_with("SOCKET_") && k.to_string_lossy() != "SOCKET_NO_CONFIG" { - cmd.env_remove(&k); - } - } - cmd.env_remove("VIRTUAL_ENV"); let _fixture = prebuilt_common::prepare_command(&mut cmd, cwd, args, &[]); let out = cmd.output().expect("failed to run socket-patch binary"); ( diff --git a/crates/socket-patch-cli/tests/e2e_vendor_golang_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_golang_build.rs index 5f91be529..852cfc0ef 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_golang_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_golang_build.rs @@ -28,7 +28,7 @@ #[path = "common/mod.rs"] mod common; use common::envelope::find_event; -use common::{binary, git_sha256, parse_json_envelope}; +use common::{binary, git_sha256, hermetic, hermetic_command, parse_json_envelope}; #[path = "prebuilt_common/mod.rs"] mod prebuilt_common; @@ -59,17 +59,13 @@ const PATCHED_LIB: &str = "package upstream\n\nfunc Greeting() string { return \ // ── self-contained helpers ──────────────────────────────────────────── -/// Run socket-patch with `SOCKET_*` scrubbed + the fixture GOMODCACHE (the -/// go crawler resolves installed modules through it). +/// Run socket-patch in the hermetic environment (`tests/common/hermetic.rs`) +/// with the fixture GOMODCACHE (the go crawler resolves installed modules +/// through it). fn run_socket(cwd: &Path, args: &[&str], modcache: &Path) -> (i32, String, String) { - let mut cmd = Command::new(binary()); + let mut cmd = hermetic_command(&binary()); + hermetic::scrub_extra(&mut cmd, &[hermetic::Extra::Venv]); cmd.current_dir(cwd); - for (k, _) in std::env::vars_os() { - if k.to_string_lossy().starts_with("SOCKET_") && k.to_string_lossy() != "SOCKET_NO_CONFIG" { - cmd.env_remove(&k); - } - } - cmd.env_remove("VIRTUAL_ENV"); cmd.env("GOMODCACHE", modcache); let _fixture = prebuilt_common::prepare_command( &mut cmd, diff --git a/crates/socket-patch-cli/tests/e2e_vendor_jvm_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_jvm_build.rs index 06fccdb3b..41c17a4b4 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_jvm_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_jvm_build.rs @@ -32,7 +32,7 @@ #[path = "common/mod.rs"] mod common; -use common::{binary, git_sha256}; +use common::{binary, git_sha256, hermetic_command}; #[path = "maven_build_common/mod.rs"] mod maven_build_common; @@ -48,7 +48,7 @@ mod jvm_fixture_repo; use std::collections::BTreeMap; use std::path::{Path, PathBuf}; -use std::process::{Command, Output}; +use std::process::Output; use gradle_build_common::{ assert_patched, configuration_reused, fixture_root, gradle_classpath, gradle_skip, init_script, @@ -65,7 +65,7 @@ const SV: &str = "1.10.0-socket.1d3c1fd2"; /// the local repository would break the plugin realm, not the project. const CLASSPATH_PLUGIN: &str = "org.apache.maven.plugins:maven-dependency-plugin:3.5.0"; -/// `socket-patch ` with ambient `SOCKET_*` scrubbed, `m2` as the Maven +/// `socket-patch ` in the hermetic environment, `m2` as the Maven /// repo and, when given, `gradle_home` as the `GRADLE_USER_HOME` the CLI /// crawls (and the fixture registry serves). fn socket_in( @@ -74,12 +74,7 @@ fn socket_in( gradle_home: Option<&Path>, args: &[&str], ) -> (Option, serde_json::Value, String) { - let mut cmd = Command::new(binary()); - for (k, _) in std::env::vars_os() { - if k.to_string_lossy().starts_with("SOCKET_") { - cmd.env_remove(&k); - } - } + let mut cmd = hermetic_command(&binary()); let mut caches = vec![("MAVEN_REPO_LOCAL", m2.to_str().unwrap())]; if let Some(home) = gradle_home { caches.push(("GRADLE_USER_HOME", home.to_str().unwrap())); @@ -87,8 +82,6 @@ fn socket_in( let _fixture = prebuilt_common::prepare_command(&mut cmd, cwd, args, &caches); let out = cmd .current_dir(cwd) - .env("SOCKET_TELEMETRY_DISABLED", "1") - .env("SOCKET_NO_CONFIG", "1") .env("MAVEN_REPO_LOCAL", m2) .env_remove("M2_HOME") .env_remove("VIRTUAL_ENV") diff --git a/crates/socket-patch-cli/tests/e2e_vendor_maven_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_maven_build.rs index 7dcce8e4f..b62b124b8 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_maven_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_maven_build.rs @@ -51,7 +51,6 @@ mod prebuilt_common; mod vex_e2e_common; use std::path::{Path, PathBuf}; -use std::process::Command; use maven_build_common::*; use vex_e2e_common::*; @@ -95,15 +94,10 @@ fn snapshot(dir: &Path) -> std::collections::BTreeMap> { out } -/// `socket-patch ` with ambient `SOCKET_*` scrubbed and the per-test +/// `socket-patch ` in the hermetic environment and the per-test /// local repository as the crawler's maven repo. fn socket(cwd: &Path, m2: &Path, args: &[&str]) -> (Option, serde_json::Value, String) { - let mut cmd = Command::new(binary()); - for (k, _) in std::env::vars_os() { - if k.to_string_lossy().starts_with("SOCKET_") { - cmd.env_remove(&k); - } - } + let mut cmd = hermetic::command(&binary()); let _fixture = prebuilt_common::prepare_command( &mut cmd, cwd, @@ -112,8 +106,6 @@ fn socket(cwd: &Path, m2: &Path, args: &[&str]) -> (Option, serde_json::Val ); let out = cmd .current_dir(cwd) - .env("SOCKET_TELEMETRY_DISABLED", "1") - .env("SOCKET_NO_CONFIG", "1") .env("MAVEN_REPO_LOCAL", m2) .env_remove("M2_HOME") .env_remove("VIRTUAL_ENV") diff --git a/crates/socket-patch-cli/tests/e2e_vendor_npm_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_npm_build.rs index 69bf6b9a1..2b6235749 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_npm_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_npm_build.rs @@ -37,7 +37,7 @@ #[path = "common/mod.rs"] mod common; -use common::{binary, git_sha256}; +use common::{binary, git_sha256, hermetic, hermetic_command}; #[path = "prebuilt_common/mod.rs"] mod prebuilt_common; @@ -68,18 +68,14 @@ const ORG: &str = "test-org"; // ── self-contained helpers ──────────────────────────────────────────── -/// Run the socket-patch binary with a scrubbed environment: every ambient -/// `SOCKET_*` var is removed (so a developer's `SOCKET_DRY_RUN=1` etc. can't -/// flip behavior) along with `VIRTUAL_ENV` (crawler discovery input). +/// Run the socket-patch binary in the hermetic environment +/// (`tests/common/hermetic.rs`: no ambient `SOCKET_*`, so a developer's +/// `SOCKET_DRY_RUN=1` etc. can't flip behavior) with `VIRTUAL_ENV` (crawler +/// discovery input) removed. fn run_socket(cwd: &Path, args: &[&str]) -> (i32, String, String) { - let mut cmd = Command::new(binary()); + let mut cmd = hermetic_command(&binary()); + hermetic::scrub_extra(&mut cmd, &[hermetic::Extra::Venv]); cmd.current_dir(cwd); - for (k, _) in std::env::vars_os() { - if k.to_string_lossy().starts_with("SOCKET_") && k.to_string_lossy() != "SOCKET_NO_CONFIG" { - cmd.env_remove(&k); - } - } - cmd.env_remove("VIRTUAL_ENV"); let _fixture = prebuilt_common::prepare_command(&mut cmd, cwd, args, &[]); let out = cmd.output().expect("failed to run socket-patch binary"); ( diff --git a/crates/socket-patch-cli/tests/e2e_vendor_pypi_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_pypi_build.rs index 09fba0879..4189802d5 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_pypi_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_pypi_build.rs @@ -56,7 +56,7 @@ #[path = "common/mod.rs"] mod common; -use common::{binary, git_sha256}; +use common::{binary, git_sha256, hermetic, hermetic_command}; #[path = "prebuilt_common/mod.rs"] mod prebuilt_common; @@ -113,18 +113,13 @@ const ORACLE: &str = "import six; print(six.SOCKET_PATCHED)"; // ── self-contained helpers ──────────────────────────────────────────── -/// Run socket-patch with ambient `SOCKET_*` + `VIRTUAL_ENV` scrubbed -/// (`VIRTUAL_ENV` is a python-crawler discovery input and must not leak from -/// the developer's shell). +/// Run socket-patch in the hermetic environment (`tests/common/hermetic.rs`) +/// with `VIRTUAL_ENV` removed (a python-crawler discovery input that must +/// not leak from the developer's shell). fn run_socket(cwd: &Path, args: &[&str]) -> (i32, String, String) { - let mut cmd = Command::new(binary()); + let mut cmd = hermetic_command(&binary()); + hermetic::scrub_extra(&mut cmd, &[hermetic::Extra::Venv]); cmd.current_dir(cwd); - for (k, _) in std::env::vars_os() { - if k.to_string_lossy().starts_with("SOCKET_") && k.to_string_lossy() != "SOCKET_NO_CONFIG" { - cmd.env_remove(&k); - } - } - cmd.env_remove("VIRTUAL_ENV"); let _fixture = prebuilt_common::prepare_command(&mut cmd, cwd, args, &[]); let out = cmd.output().expect("failed to run socket-patch binary"); ( diff --git a/crates/socket-patch-cli/tests/spawn_env_hygiene.rs b/crates/socket-patch-cli/tests/spawn_env_hygiene.rs index 70169605b..4a441ea12 100644 --- a/crates/socket-patch-cli/tests/spawn_env_hygiene.rs +++ b/crates/socket-patch-cli/tests/spawn_env_hygiene.rs @@ -48,16 +48,6 @@ const PENDING_RAW_SPAWNS: &[&str] = &[ "e2e_redirect_cargo_shapes.rs", "e2e_scan.rs", "e2e_socket_yml_policy.rs", - "e2e_vendor_bun_build.rs", - "e2e_vendor_cargo_build.rs", - "e2e_vendor_composer_build.rs", - "e2e_vendor_composer_crlf.rs", - "e2e_vendor_gem_build.rs", - "e2e_vendor_golang_build.rs", - "e2e_vendor_jvm_build.rs", - "e2e_vendor_maven_build.rs", - "e2e_vendor_npm_build.rs", - "e2e_vendor_pypi_build.rs", "e2e_vendored_production.rs", "e2e_vex_vendor.rs", "rollback/rollback_multicopy_blob_gate.rs", From 230c44accb8833924a01e911e5385898971de29e Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 13 Oct 2026 14:17:03 +0000 Subject: [PATCH 3/4] Drop uv venv override and share venv scrub The pypi vendor suite's leak guards set UV_PROJECT_ENVIRONMENT in the test process, and the python crawler reads it, so every socket-patch child it spawned inherited a bogus venv path. Remove it (Extra::Pdm) along with VIRTUAL_ENV. The maven and jvm suites now drop VIRTUAL_ENV through Extra::Venv like the rest instead of a hand-written removal. Assisted-by: Claude Code:claude-opus-5-5 --- crates/socket-patch-cli/tests/e2e_vendor_jvm_build.rs | 4 ++-- crates/socket-patch-cli/tests/e2e_vendor_maven_build.rs | 2 +- crates/socket-patch-cli/tests/e2e_vendor_pypi_build.rs | 7 ++++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/crates/socket-patch-cli/tests/e2e_vendor_jvm_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_jvm_build.rs index 41c17a4b4..2e1f00754 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_jvm_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_jvm_build.rs @@ -32,7 +32,7 @@ #[path = "common/mod.rs"] mod common; -use common::{binary, git_sha256, hermetic_command}; +use common::{binary, git_sha256, hermetic, hermetic_command}; #[path = "maven_build_common/mod.rs"] mod maven_build_common; @@ -75,6 +75,7 @@ fn socket_in( args: &[&str], ) -> (Option, serde_json::Value, String) { let mut cmd = hermetic_command(&binary()); + hermetic::scrub_extra(&mut cmd, &[hermetic::Extra::Venv]); let mut caches = vec![("MAVEN_REPO_LOCAL", m2.to_str().unwrap())]; if let Some(home) = gradle_home { caches.push(("GRADLE_USER_HOME", home.to_str().unwrap())); @@ -84,7 +85,6 @@ fn socket_in( .current_dir(cwd) .env("MAVEN_REPO_LOCAL", m2) .env_remove("M2_HOME") - .env_remove("VIRTUAL_ENV") .output() .expect("run socket-patch"); let stdout = String::from_utf8_lossy(&out.stdout).into_owned(); diff --git a/crates/socket-patch-cli/tests/e2e_vendor_maven_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_maven_build.rs index b62b124b8..3c0723af7 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_maven_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_maven_build.rs @@ -98,6 +98,7 @@ fn snapshot(dir: &Path) -> std::collections::BTreeMap> { /// local repository as the crawler's maven repo. fn socket(cwd: &Path, m2: &Path, args: &[&str]) -> (Option, serde_json::Value, String) { let mut cmd = hermetic::command(&binary()); + hermetic::scrub_extra(&mut cmd, &[hermetic::Extra::Venv]); let _fixture = prebuilt_common::prepare_command( &mut cmd, cwd, @@ -108,7 +109,6 @@ fn socket(cwd: &Path, m2: &Path, args: &[&str]) -> (Option, serde_json::Val .current_dir(cwd) .env("MAVEN_REPO_LOCAL", m2) .env_remove("M2_HOME") - .env_remove("VIRTUAL_ENV") .output() .expect("run socket-patch"); let stdout = String::from_utf8_lossy(&out.stdout).into_owned(); diff --git a/crates/socket-patch-cli/tests/e2e_vendor_pypi_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_pypi_build.rs index 4189802d5..820f76795 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_pypi_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_pypi_build.rs @@ -114,11 +114,12 @@ const ORACLE: &str = "import six; print(six.SOCKET_PATCHED)"; // ── self-contained helpers ──────────────────────────────────────────── /// Run socket-patch in the hermetic environment (`tests/common/hermetic.rs`) -/// with `VIRTUAL_ENV` removed (a python-crawler discovery input that must -/// not leak from the developer's shell). +/// with `VIRTUAL_ENV` and `UV_PROJECT_ENVIRONMENT` removed: both are +/// python-crawler discovery inputs that must not leak from the developer's +/// shell, and `bake_leak_guards` sets the latter in this process. fn run_socket(cwd: &Path, args: &[&str]) -> (i32, String, String) { let mut cmd = hermetic_command(&binary()); - hermetic::scrub_extra(&mut cmd, &[hermetic::Extra::Venv]); + hermetic::scrub_extra(&mut cmd, &[hermetic::Extra::Venv, hermetic::Extra::Pdm]); cmd.current_dir(cwd); let _fixture = prebuilt_common::prepare_command(&mut cmd, cwd, args, &[]); let out = cmd.output().expect("failed to run socket-patch binary"); From 00f01c7e108c10d2c4d855f3f0d5e68a8f698b28 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 13 Oct 2026 14:32:23 +0000 Subject: [PATCH 4/4] Serialize npm mirror tarball test project_registry_decides_a_mirrors_tarball_urls falls back to the SOCKET_NPM_REGISTRY env var, which the bun_lockb and vlt tests set to a wiremock URL under #[serial]. This test was not serial, so it could read their value and fail, as it did on the coverage job for #1484. Mark it #[serial] like the client.rs tests that read the same var. Assisted-by: Claude Code:claude-opus-5-5 --- crates/socket-patch-core/src/patch/redirect/upstream/npm.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/socket-patch-core/src/patch/redirect/upstream/npm.rs b/crates/socket-patch-core/src/patch/redirect/upstream/npm.rs index 156cfcd17..8ebb95001 100644 --- a/crates/socket-patch-core/src/patch/redirect/upstream/npm.rs +++ b/crates/socket-patch-core/src/patch/redirect/upstream/npm.rs @@ -4024,7 +4024,10 @@ mod tests { ); } + // The `from_project: false` fallback reads `SOCKET_NPM_REGISTRY`, which + // serial tests (bun_lockb, vlt) set to a wiremock URL. #[test] + #[serial_test::serial] fn project_registry_decides_a_mirrors_tarball_urls() { // A metadata mirror that hands back the project registry's own URLs: // the package manager derives them, so they stay out of the lock.