#14290·pip

git+ VCS installs leak GIT_INDEX_FILE, corrupting the caller's git index

Author: dawid-czarneckiCreated Aug 30, 2026Updated Aug 30, 2026

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

bash
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 errors

Confirmed 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:

python
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.