Skip to content

fix(core): scrub GIT_* env when spawning git so git hooks can't corrupt the repo#149

Merged
oratis merged 1 commit into
mainfrom
fix/git-env-scrub
Jun 3, 2026
Merged

fix(core): scrub GIT_* env when spawning git so git hooks can't corrupt the repo#149
oratis merged 1 commit into
mainfrom
fix/git-env-scrub

Conversation

@oratis
Copy link
Copy Markdown
Owner

@oratis oratis commented Jun 2, 2026

Summary

git resolves the repository from GIT_DIR / GIT_WORK_TREE / GIT_INDEX_FILE in the environment before the directory it runs in. When the suite runs inside a contributor's pre-commit hook (husky → pnpm test), git exports those vars and they leak into the test subprocesses — git init in a test's temp repo then targets the real repo's git dir with no work tree and re-initializes it as bare (core.bare=true), breaking every worktree (fatal: this operation must be run in a work tree). snapshots.ts's production git() helper had the same exposure.

This extracts the GIT_*-stripping that worktree/index.ts already did inline into a shared gitSpawnEnv() helper and uses it in snapshots.ts, worktree/index.ts (dedupe), and the snapshots/worktree test setups. Exported from @deepcode/core.

Test plan

  • pnpm typecheck
  • Ran snapshots + worktree-tools + new git-env suites with GIT_DIR/GIT_INDEX_FILE set to bogus paths (simulating the hook) → 15 passing, and core.bare stayed false (repo not corrupted). Before this change that run failed and corrupted the repo.
  • prettier --check + eslint clean
  • CI green (ubuntu + macOS)

Adds git-env.test.ts (unit) covering the strip/preserve/no-mutate behavior.

Documentation

  • N/A — internal robustness fix; // why: comment in git-env.ts explains the hazard.

Release notes label

  • release-notes:fix

Related

Discovered while opening PRs during a Codex/Claude Code/DeepCode alignment review — the pre-commit hook corrupted this worktree (core.bare=true) the first time the suite ran inside a commit.

…pt the repo

git resolves the repository from GIT_DIR / GIT_WORK_TREE / GIT_INDEX_FILE in the
environment before the directory it runs in. When the test suite runs inside a
contributor's pre-commit hook, git exports those vars and they leak into the
test subprocesses: `git init` in a temp repo then targets the real repo's git
dir with no work tree and re-initializes it as bare (core.bare=true), breaking
every worktree. snapshots.ts's production git() helper had the same exposure.

Add a shared gitSpawnEnv() helper (extracted from worktree/index.ts's existing
inline scrub) that strips GIT_* from the env, and use it in snapshots.ts, in
worktree/index.ts (dedupe), and in the snapshots/worktree test setups. Export it
from @deepcode/core for reuse by other git-spawning code.

Validated by running the snapshots + worktree-tools suites with GIT_DIR and
GIT_INDEX_FILE set to bogus paths (simulating the hook): all green and core.bare
stays false. Adds a gitSpawnEnv unit test.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@oratis oratis merged commit cac086d into main Jun 3, 2026
3 checks passed
@oratis oratis deleted the fix/git-env-scrub branch June 3, 2026 17:02
oratis added a commit that referenced this pull request Jun 3, 2026
… Claude parity) (#150)

Codex and Claude Code both expose /diff and /release-notes; Claude also has
/bug (/feedback). DeepCode had none of them.

- /diff: `git status --short` + `git diff HEAD` (truncated to 300 lines) +
  untracked files, in the session cwd. Clean message outside a git repo.
- /release-notes: prints the latest CHANGELOG.md section (walks up from cwd).
- /bug (alias /feedback): prints a prefilled github.com/oratis/deepcode issue
  link, carrying the current model/mode/effort in the body.

git is spawned with GIT_* stripped from the env (inlined to keep this PR
independent of #149) so a leaked GIT_DIR can't redirect it. Adds 6 tests.

Co-authored-by: t <t@t>
Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant