git+ VCS installs leak GIT_INDEX_FILE, corrupting the caller's git index
Description
When pip installs a git+ VCS requirement, it shells out to git clone/git checkout. Git.unset_environ in pip/_internal/vcs/git.py already strips GIT_DIR and GIT_WORK_TREE from these subprocesses to prevent ambient env vars from interfering (#1130), but it does not strip GIT_INDEX_FILE.
git itself sets GIT_INDEX_FILE in the environment when invoking hooks (e.g. pre-commit), pointing at the index of the repo/worktree currently being committed. If that hook runs pip install (directly, or via a tool like pip-audit) against a requirement pinned with git+..., the inherited GIT_INDEX_FILE causes pip's own git checkout — run inside its throwaway temp clone of the dependency — to write its checked-out tree into the caller's index instead of its own. Those index entries reference blobs that only exist in pip's temp clone (deleted right after pip finishes), so the caller's repo comes back corrupted:
error: <sha>: invalid sha1 pointer in cache-tree
missing blob <sha>
missing blob <sha>
...This is fully deterministic — no race or concurrency needed, one git commit is enough.
Reproduction
BASE=/tmp/pip-audit-repro; rm -rf "$BASE"; mkdir -p "$BASE"; cd "$BASE"
git init -q main-repo && cd main-repo
git config user.email [email protected] && git config user.name t
echo init > README.md && git add README.md && git commit -q -m init
git worktree add -q -b feature ../wt-feature
VCS_LINE="git+https://github.com/LImoritakeU/django-admin-honeypot.git@958fb8bf5d8c30c13d8256c955b07eb32f6807be"
cat > .git/hooks/pre-commit <<HOOK
#!/bin/bash
python3 -m pip install --dry-run --report /tmp/report.json --no-input "$VCS_LINE" >/tmp/pip.log 2>&1
exit 0
HOOK
chmod +x .git/hooks/pre-commit
cd "$BASE/wt-feature"
echo "$VCS_LINE" > requirements.txt
git add requirements.txt
git commit -q -m x
git fsck --no-dangling # -> missing blob errorsConfirmed on pip 25.3 / git 2.34.1 / Python 3.13, Linux.
Suggested fix
Add GIT_INDEX_FILE to the existing allowlist in pip/_internal/vcs/git.py:
unset_environ = ("GIT_DIR", "GIT_WORK_TREE", "GIT_INDEX_FILE")Verified locally: with this one-line change, the exact same reproduction above leaves git fsck clean (exit 0, no output) instead of reporting missing blobs.
Source: pypa/pip