Repository navigation
Pipenv stale-install remedy can't replace a base-interpreter copy in a --site-packages venv: pip uninstall refuses it and pipenv sync keeps it, so following the warning leaves the package unpatched #1450
Description
[agent] Found by the scheduled Pipenv bug-hunt routine (ledger #313).
Summary
Since #1419 (#409), the hosted and vendored stale-install warnings correctly fire when a pipenv --site-packages / PIPENV_SITE_PACKAGES=1 venv imports the upstream release from its base interpreter (e.g. Debian's /usr/lib/python3/dist-packages/six.py). But the warning still prints the generic Pipenv remedy from stale_install_remedy, and neither command it names works for a base copy:
pipenv run pip uninstall -y six && pipenv sync: pip refuses withNot uninstalling six at /usr/lib/python3/dist-packages, outside environment <venv>/Can't uninstall 'six'. Thenpipenv syncsees six 1.16.0 already satisfied by the base copy, says "All dependencies are now up-to-date!", and installs nothing.pipenv --rm && pipenv sync: withPIPENV_SITE_PACKAGES=1set (or the user recreating the venv with--site-packagesas their project requires), the new venv inherits the same base copy, and sync again installs nothing.
After either remedy the venv still imports upstream six. The next scan prints the same warning and the same remedy, so the user loops. The warning also says "the rewritten Pipfile.lock only protects fresh installs", but a fresh --site-packages venv on the same host also keeps the base copy. The lock protects nothing there.
It fails closed (vex gives not_applied, and the warning re-fires), so nothing is falsely attested. The defect is that the printed remedy, which pipenv-compatibility.md documents as verified, cannot work in this shape.
Impact
Any Pipenv project using --site-packages / PIPENV_SITE_PACKAGES=1 whose base interpreter carries the same release (common with distro python3-* packages and Docker base images). Users follow the remedy, see it fail, and can't reach a patched install without knowing a pip-level workaround.
Repro (Linux, Debian/Ubuntu python3.11 with python3-six 1.16.0 in /usr/lib/python3/dist-packages)
export WORKON_HOME=$PWD/workon PIPENV_SITE_PACKAGES=1
mkdir proj && cd proj
cat > Pipfile <<'EOF'
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
six = "==1.16.0"
EOF
pipenv --python /usr/bin/python3.11 lock && pipenv sync
pipenv run python -c 'import six; print(six.__file__)' # /usr/lib/python3/dist-packages/six.py
socket-patch scan --mode hosted --yes ... # (or --mode vendored); warns: installed files in /usr/lib/python3/dist-packages still differ ...
# remedy 1, verbatim
pipenv run pip uninstall -y six && pipenv sync # "Can't uninstall 'six'" / "All dependencies are now up-to-date!"
pipenv run python -c 'import six; print(six.__file__)' # still /usr/lib/python3/dist-packages/six.py (upstream)
# remedy 2, verbatim
pipenv --rm && pipenv sync
pipenv run python -c 'import six; print(six.__file__)' # still /usr/lib/python3/dist-packages/six.py (upstream)
socket-patch scan --mode hosted ... # same warning, same remedy
socket-patch vex --product pkg:pypi/proj@1 -O vex.json # omits six: not_applied (correct)I used a local mock patch API that serves a patched six-1.16.0 wheel. The oracle is the first line of the imported six.py.
A command that does work (the base copy stays untouched, and the venv gets the patched wheel):
pipenv run pip install --no-deps --ignore-installed -r <(pipenv requirements), with the lock's category args on pipenv requirements.
Expected vs actual
- Expected: docs/testing/pipenv-compatibility.md ("Warm virtualenvs are never reinstalled") presents the two printed commands as the verified remedies, and the warning tells the user how to get a patched install. When the stale copy is in a base-interpreter site dir the venv inherits (one of the dirs Fix crawl of --system-site-packages venvs (#409) #1419 added), the remedy should name a command that installs over it inside the venv (e.g. the
pip install --no-deps --ignore-installedform above). Otherwise it should say plainly that the base copy shadows the lock, and drop the "only protects fresh installs" claim. - Actual: the same generic remedy, which leaves the package unpatched on every attempt.
OS × version
| OS | Pipenv | hosted warning fires | remedy 1 (pip uninstall && sync) |
remedy 2 (--rm && sync, PIPENV_SITE_PACKAGES=1) |
vex |
|---|---|---|---|---|---|
| Linux | 2022.12.19 (py3.11) | yes | fails | n/a (Pipenv 2022 recreated on py3.13, harness quirk) | — |
| Linux | 2023.12.1 (py3.11) | yes | fails (2/2) | fails | not_applied |
| Linux | 2026.8.0 (py3.11) | yes (hosted + vendored) | fails (2/2) | fails | not_applied |
| macOS / Windows | any | untested (probe branches blocked) |
Not a regression. Before #1419 no warning fired at all (#409).
Suspect code
crates/socket-patch-core/src/vendor/pypi_pipenv.rs:786stale_install_remedy: one remedy for every site dir.crates/socket-patch-cli/src/commands/scan/hosted/python.rs:143(hosted) andcrates/socket-patch-core/src/vendor/pypi.rs:780(vendored) build the warning, already know the site dir (/usr/lib/python3/dist-packages), and could tell a base dir from the venv's own.- The same question probably applies to the pip / uv / Poetry remedies for base copies, but I only tested Pipenv.
Tested on main 6ad6add (v5.0.0).
Activity
mikolalysenko commentedon Oct 12, 2026
[agent] Triaged:
priority:p1(Pipenv / PyPI family). Confirmed onmain(6ad6add): both the hosted warning (commands/scan/hosted/python.rs:136) and the vendored one (vendor/pypi.rs:776) callpypi_pipenv::stale_install_remedywith only the lock and the package name, so the remedy never depends on whether the stale dir is the venv's own site-packages or a base-interpreter dir the venv inherits through--site-packages(the dirs #1419 added). Both callers already hold the stale site dir. Not a duplicate: #409/#1419 made the warning fire, this is about what it tells the user to do. No open PR covers it, and it does not share a root cause with #1447 (Poetry 1.3 stamp) or #1445 (uv orphaned hosted wiring).Generated by Claude Code
mikolalysenko commentedon Oct 12, 2026
[agent] Claiming this issue (shared root cause:
stale_install_remedyprints one Pipenv remedy whatever site dir holds the stale copy). Branch: agent/fix-pipenv-base-site-remedy. Claim-ID: 2026-10-12T23:21:09Z-c2f8d4Generated by Claude Code
mikolalysenko commentedon Oct 12, 2026
[agent] Draft PR: #1455
Generated by Claude Code
Fix Pipenv remedy for base-interpreter copies
chore(release): 5.0.1 (#1485)
mikolalysenko commentedon Oct 13, 2026
[agent] Pipenv bug-hunt re-verification on main
aa85c6c(5.0.1), Linux, real Pipenv. I followed the new install-over remedy verbatim, and in every cell the venv then imports the patched six. The re-scan gives no warning, and vex givesnot_affected:/usr/lib/python3/dist-packagesbase,[packages][dev-packages]only (--dev)[docs]only (--categories "docs")[packages]~/.localuser siteOne gap: a pin in two or more categories with one of them named prints
--categories "packages docs", which Pipenv 2022.12.x–2023.2.4 export as empty. Filed as #1507.Generated by Claude Code
pipenv: 2026-10-13 21:35Z bug-hunt run (#1507, #1450 verified)