Skip to content

Agent mode honours the Pipfile's [pipenv] venv_in_project = true for every Pipenv, but only 2026.2+ read it, so on Pipenv 2018–2026.1 the WORKON_HOME venv stays unpatched, the system Python is patched instead, and VEX attests not_affected #842

Description

[agent] Found by the scheduled Pipenv bug-hunt routine (ledger #313).

Summary

pipenv_venv_in_project (crates/socket-patch-core/src/crawlers/python_crawler.rs:668) reads the Pipfile's [pipenv] venv_in_project key for every Pipenv project. If the key is true and ./.venv doesn't exist, pipenv_project_site_packages returns no venv at all (python_crawler.rs:711, "An explicit 'in project' with no ./.venv means Pipenv has no venv yet").

That holds only for Pipenv 2026.2.0+, the first release that reads the key (Project._pipfile_venv_in_project). Pipenv 2018.11.26 through 2026.1.0 ignore it and put the venv at $WORKON_HOME/<name>-<hash> as usual. So when a team commits venv_in_project = true and a developer, CI image or distro still runs Pipenv ≤ 2026.1, the real venv is never found:

This is the mirror image of the venv_in_project = false case, which PR #654 already treats as "only 2026.2+ reads it". The = true case with no ./.venv is unchanged in #654 (its test only covers = true with a ./.venv present, which is correct for every version). I re-ran the repro on the #654 head d8356ae and it still fails.

Impact

A silent miss with a false attestation, plus an unrequested write into the system interpreter. A team that adopts the documented Pipenv 2026.2 setting gets wrong results on every older Pipenv in its fleet.

Repro (Linux, real Pipenv)

export WORKON_HOME=/tmp/wh PIPENV_YES=1
mkdir proj && cd proj
printf '[[source]]\nurl = "https://pypi.org/simple"\nverify_ssl = true\nname = "pypi"\n\n[packages]\nsix = "==1.16.0"\n\n[pipenv]\nvenv_in_project = true\n' > Pipfile
pipenv install            # Pipenv 2025.1.3: venv at $WORKON_HOME/proj-<hash>, no ./.venv
pipenv --venv             # -> /tmp/wh/proj-qzUn2fQZ
socket-patch scan --mode agent --yes        # patch API serving a six 1.16.0 patch
pipenv run python -c "import six; print(getattr(six, 'SOCKET_PATCHED', 'UNPATCHED'))"   # UNPATCHED
sha256sum /usr/lib/python3/dist-packages/six.py                                         # changed: the system copy was patched
socket-patch vex --product pkg:pypi/demo@1.0.0 --output vex.json                        # statement: not_affected

Patch data came from a local mock patch API (batch / by-package / view / blob) serving a six 1.16.0 patch that appends SOCKET_PATCHED = True. socket-patch rollback --yes restored the system six.py byte-identically.

Expected vs actual

Matrix (Linux, main 045d7ec, 2/2 runs each)

Pipenv venv Pipenv uses pipenv run six after scan system six vex result
2018.11.26 (py3.8) $WORKON_HOME/proj-… UNPATCHED patched not_affected fail
2023.12.1 $WORKON_HOME/proj-… UNPATCHED patched not_affected fail
2023.12.1, venv_in_project = "yes" $WORKON_HOME/proj-… UNPATCHED patched not_affected fail
2025.1.3 $WORKON_HOME/proj-… UNPATCHED patched not_affected fail
2026.1.0 $WORKON_HOME/proj-… UNPATCHED patched not_affected fail
2026.8.0 ./.venv patched untouched not_affected pass
2025.1.3, no [pipenv] key (control) $WORKON_HOME/proj-… patched untouched not_affected pass
PR #654 head d8356ae, 2023.12.1 / 2025.1.3 $WORKON_HOME/proj-… UNPATCHED patched not_affected fail

macOS and Windows weren't probed (probe branches are blocked, see the ledger). The code path doesn't depend on the OS.

First bad commit

The Pipfile key was first read in ccd43f5 (#388, "Fix Pipenv venv discovery order"), according to git log -S venv_in_project. I didn't build its parent for this shape.

Suspect code

  • crates/socket-patch-core/src/crawlers/python_crawler.rs:668 (pipenv_venv_in_project): the Pipfile key is treated as authoritative, like the env var.
  • crates/socket-patch-core/src/crawlers/python_crawler.rs:711: in_project == Some(true) && !dot_venv.exists() returns no venv.
  • The hosted stale-install warning (crates/socket-patch-cli/src/commands/scan/hosted/python.rs:53) goes through the same find_local_venv_site_packages, so I'd expect it to miss a warm WORKON_HOME venv in this shape too. I haven't verified that in this run.

Related: #645 (the env-var form, "not in project"), #504 (the global fallback that turns this miss into a system-Python write) and PR #654.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions