From 0cc7627eb13311a2164cf8832538b08a8115f5b9 Mon Sep 17 00:00:00 2001 From: Nick Gomez <122398915+nick-inkeep@users.noreply.github.com> Date: Tue, 28 Jul 2026 21:46:19 -0700 Subject: [PATCH] fix: harden pre-push against GIT_DIR-leak core.bare corruption (#2984) * [wip] claim work on fix-core-bare-gitdir-leak * fix: gate the GIT_DIR-leak core.bare corruption class at pre-push Scrub hook-exported GIT_* in both pre-push hooks before any step runs, heal a pre-existing core.bare=true loudly at hook start, and fail the push (restoring the config) when core.bare flips mid-run. Fix the live writer (select-beta-to-promote.test.mjs fixture helper, introduced by PR 2957) with gitCleanEnv, widen gitCleanEnv to the root 8-var scrub list, and scrub the latent sites (guard-branch-switch and resolve-subtree-dirs shell fixtures, sync-open-knowledge-upstream, lume-patch apply.sh, visimer bridge fork). Add check:git-env-scrub, a zero-dep gate over hook-reachable script trees that also pins the hook scrub lines, with bidirectional self-tests, and Fixture D behavioral tests running the real hooks under a poisoned GIT_DIR. Document the symptom playbook in CI_RUNBOOK and the incident audit in public/open-knowledge/reports/core-bare-corruption-audit. * review: fix scrub comments, warn on unreadable scan dirs Correct the lume-patch scrub comment (clone, not init), enumerate all scrub-helper copies from the authoritative GIT_SCRUB_VARS comment, and make the scanner warn on non-ENOENT directory read errors instead of silently skipping. * review: mirror git-clean-env.mjs, fix guard comment, merge caller env Add git-clean-env.mjs to the public-open-knowledge Copybara allowlist (the mirrored release scripts now import it; without the entry the public repo's promote-stable and select-beta workflows would fail at module load) and regenerate the config. Correct the core_bare_is_true guard comment (the missing-config branch is deliberately not-corrupt, not fail-closed), merge caller env before the scrub in cc-task runChild, and fix a stale fixture count in the gate self-test docs. * review: verify steps fire after heal, enumerate bridge scrub copies Fixture D's heal test now asserts all six step sentinels fired after the repair (healing must let the run proceed), and the GIT_SCRUB_VARS sync comment enumerates the two bridge-script inline destructures alongside the four named helpers. GitOrigin-RevId: 05cc8f04e8311cfbe93fd73909b8bfe09f31334a --- .../scripts/bridge-public-pr-to-monorepo.mjs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/scripts/bridge-public-pr-to-monorepo.mjs b/.github/scripts/bridge-public-pr-to-monorepo.mjs index 664c53c..24fb619 100644 --- a/.github/scripts/bridge-public-pr-to-monorepo.mjs +++ b/.github/scripts/bridge-public-pr-to-monorepo.mjs @@ -24,11 +24,30 @@ function sanitizeErrorMessage(value) { } function run(command, args, options = {}) { + // Drop inherited GIT_* repo-targeting vars: every git spawn in + // this script targets an explicit clone/worktree via cwd, never the repo a + // calling git hook belongs to. In CI these variables are unset (no-op); + // locally they leak from pre-push/pre-commit hooks into harnesses that + // import this module and break explicit-cwd git. + // Sanitize AFTER merging a caller-supplied env so the guarantee is + // unconditional — an options.env override must not reintroduce the vars. + const { + GIT_DIR: _d, + GIT_WORK_TREE: _w, + GIT_COMMON_DIR: _c, + GIT_INDEX_FILE: _i, + GIT_OBJECT_DIRECTORY: _o, + GIT_ALTERNATE_OBJECT_DIRECTORIES: _a, + GIT_NAMESPACE: _n, + GIT_PREFIX: _p, + ...cleanEnv + } = { ...process.env, ...options.env }; try { return execFileSync(command, args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], ...options, + env: cleanEnv, }).trim(); } catch (error) { const stderr = sanitizeErrorMessage(error.stderr?.toString().trim() ?? '');