Commit Graph

1 Commits

Author SHA1 Message Date
Andy 7cb9e0a335 fix(worktree): prevent cross-worktree file leakage via environment variables (#1267)
* fix(worktree): prevent cross-worktree file leakage via environment variables

When pre-commit hook runs in a worktree, it sets GIT_DIR and GIT_WORK_TREE
environment variables. These variables were persisting and leaking into
subsequent git operations in other worktrees or the main repository, causing
files to appear as untracked in the wrong location.

Root cause confirmed by 5 independent investigation agents:
- GIT_DIR/GIT_WORK_TREE exports persist across shell sessions
- Version sync section runs git add without env isolation
- Tests already clear these vars but production code didn't

Fix:
- Clear GIT_DIR/GIT_WORK_TREE when NOT in a worktree context
- Add auto-detection and repair of corrupted core.worktree config
- Add comprehensive documentation explaining the bug and fix

* fix(worktree): add git env isolation to frontend subprocess calls

Extend worktree corruption fix to TypeScript frontend:

- Create git-isolation.ts utility with getIsolatedGitEnv()
- Fix task/worktree-handlers.ts: merge, preview, PR creation spawns
- Fix terminal/worktree-handlers.ts: all 10 execFileSync git calls
- Use getToolPath('git') consistently for cross-platform support

Clears GIT_DIR, GIT_WORK_TREE, GIT_INDEX_FILE, and author/committer
env vars to prevent cross-contamination between worktrees.

Part of fix for mysterious file leakage between worktrees.

* fix(pre-commit): improve robustness of git worktree handling

Address PR review findings:

1. Improve .git file parsing for worktree detection:
   - Use sed -n with /p to only print matching lines
   - Add head -1 to handle malformed files with multiple lines
   - Add directory existence check before setting GIT_DIR

2. Add error handling for git config --unset:
   - Wrap in conditional to detect failures
   - Print warning if unset fails (permissions, locked config, etc.)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(worktree): align git env isolation between TypeScript and Python

Address PR review findings for consistency:

1. Add GIT_AUTHOR_DATE and GIT_COMMITTER_DATE to TypeScript
   GIT_ENV_VARS_TO_CLEAR array to match Python implementation

2. Add HUSKY=0 to Python get_isolated_git_env() to match
   TypeScript implementation and prevent double-hook execution

3. Add getIsolatedGitEnv() to listOtherWorktrees() for consistency
   with all other git operations in the file

Also fix ruff linting (UP045): Replace Optional[dict] with dict | None

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(workspace): migrate remaining git calls to use run_git for env isolation

Replace all direct subprocess.run git calls in workspace.py with run_git()
to ensure consistent environment isolation across all backend git operations.

This prevents potential cross-worktree contamination from environment
variables (GIT_DIR, GIT_WORK_TREE, etc.) that could be set by pre-commit
hooks or other git configurations.

Converted 13 subprocess.run calls:
- git rev-parse --abbrev-ref HEAD
- git merge-base (2 locations)
- git add (10 locations)

Also:
- Remove now-unused subprocess import
- Fix cross-platform issue: use getToolPath('git') in listOtherWorktrees

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(worktree): add unit tests and fix pythonEnv git isolation bypass

- Add comprehensive Python tests for git_executable module (20 tests)
- Add TypeScript tests for getIsolatedGitEnv utility (19 tests)
- Migrate GitLab handlers to use getIsolatedGitEnv for git commands
- Fix critical bug: getPythonEnv() now uses getIsolatedGitEnv() as base
  to prevent git env vars from being re-added when pythonEnv is spread

The pythonEnv bypass bug caused git isolation to be defeated when:
  env: { ...getIsolatedGitEnv(), ...pythonEnv, ... }
because pythonEnv contained a copy of process.env with git vars intact.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(worktree): add git env isolation to execution-handlers

Add getIsolatedGitEnv() to 6 git commands in execution-handlers.ts:
- QA review rejection: reset, checkout, clean (lines 407-430)
- Task discard cleanup: rev-parse, worktree remove, branch -D (lines 573-599)

Without env isolation, these commands could operate on the wrong
repository if GIT_DIR/GIT_WORK_TREE vars were set from a previous
worktree operation.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(pre-commit): clear git env vars when worktree detection fails

When .git is a file but WORKTREE_GIT_DIR parsing fails (empty or invalid
directory), any inherited GIT_DIR/GIT_WORK_TREE environment variables
were left in place, potentially causing cross-worktree contamination.

Now explicitly unsets these variables in the failure case, matching the
behavior of the main repo branch.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore(tests): remove unused pytest import

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 00:04:23 +01:00