fix(#2665): scrub config-location env on the parent for in-process install()

The blocker the review said decides this PR. These tests call the real installer
IN-PROCESS with only HOME/USERPROFILE sandboxed. getGlobalConfigDir is env-first,
so an ambient CLAUDE_CONFIG_DIR beats the sandbox and a complete global install --
agents/, commands/, skills/, gsd-core/, manifest, settings -- lands in the
developer's live config dir. No child-env scrub can reach it; only clearing the
parent's env can.

The review named two describe blocks in install.test.cjs. A sweep for the shape
found four there (bug #3571 and bug #3288 each appear twice in the file), and the
post-suite guard added later in this series found a fifth in
runtime-artifact-layout.test.cjs, which the review did not name. All five now
save/clear/restore via scrubConfigLocationEnv().

Verified: codebuddy-install, cline-install and codex-config already guard their
own config-location var around in-process install(), so the class is closed.

Addresses review finding: Blocker 1.
This commit is contained in:
0xdhx
2026-07-28 06:05:16 -05:00
parent bc5c362610
commit 466db2f1a3
2 changed files with 45 additions and 5 deletions

View File

@@ -26,7 +26,7 @@ const { resolveRuntimeArtifactLayout, findInstallSourceRoot } = require('../gsd-
const capabilityRegistry = require('../gsd-core/bin/lib/capability-registry.cjs');
const installProfiles = require('../gsd-core/bin/lib/install-profiles.cjs');
const { install } = require('../bin/install.js');
const { createTempDir, cleanup } = require('./helpers.cjs');
const { createTempDir, cleanup, scrubConfigLocationEnv } = require('./helpers.cjs');
const REPO_ROOT = path.join(__dirname, '..');
@@ -687,6 +687,7 @@ describe('#1477 .gsd-source marker provisioning', () => {
let savedUserProfile;
let savedExplicitConfigDir;
let savedTestMode;
let restoreConfigLocationEnv;
function silenceConsole(fn) {
const orig = { log: console.log, warn: console.warn, error: console.error };
@@ -732,6 +733,12 @@ describe('#1477 .gsd-source marker provisioning', () => {
delete process.env.GSD_EXPLICIT_CONFIG_DIR;
savedTestMode = process.env.GSD_TEST_MODE;
process.env.GSD_TEST_MODE = '1';
// #2665: this block calls install(true, 'claude') IN-PROCESS. Redirecting
// HOME/USERPROFILE is not enough, because getGlobalConfigDir is env-FIRST:
// an ambient CLAUDE_CONFIG_DIR wins over the fixture and a full global
// install lands in the developer's live config dir. Found by the post-suite
// hermeticity guard (scripts/live-config-guard.cjs), not by inspection.
restoreConfigLocationEnv = scrubConfigLocationEnv();
});
afterEach(() => {
@@ -743,6 +750,7 @@ describe('#1477 .gsd-source marker provisioning', () => {
else process.env.GSD_EXPLICIT_CONFIG_DIR = savedExplicitConfigDir;
if (savedTestMode === undefined) delete process.env.GSD_TEST_MODE;
else process.env.GSD_TEST_MODE = savedTestMode;
restoreConfigLocationEnv();
cleanup(tmpRoot);
});