Skip to content

Agent mode skips ./.venv when PIPENV_VENV_IN_PROJECT=0 or PIPENV_NO_VENV_IN_PROJECT=1 is set, but Pipenv 2018 through 2023.10.24 still use that .venv, so it stays unpatched and VEX attests not_affected (regression from #388) #645

Description

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

Summary

Since #388 (ccd43f5, the #334 fix), Pipenv venv discovery treats an explicit "not in project" setting as "ignore ./.venv". That covers PIPENV_VENV_IN_PROJECT=0 / false / off / no and PIPENV_NO_VENV_IN_PROJECT=1. In that case socket-patch returns only the $WORKON_HOME venv. The doc comment says this is because "Pipenv 2023+ ignores ./.venv then", but it only became true in Pipenv 2023.11.14. Every earlier release uses an existing ./.venv directory no matter what these variables say:

  • 2022.x through 2023.10.24, Project.get_location_for_virtualenv: # If .venv in project root is a directory, use it. / if os.path.isdir(dot_venv): return dot_venv. is_venv_in_project() is never consulted once .venv exists.
  • 2023.11.14+: if not os.path.exists(dot_venv) or os.path.isdir(dot_venv): if self.is_venv_in_project(): return dot_venv … so an explicit False falls through to WORKON_HOME. This is the behaviour Fix Pipenv venv discovery order (#334, #384) #388 modelled.
  • 2018.11.26: PIPENV_VENV_IN_PROJECT = bool(os.environ.get("PIPENV_VENV_IN_PROJECT")), so "0" and "false" are truthy (in project). PIPENV_NO_VENV_IN_PROJECT doesn't exist. On top of that, an existing .venv directory always wins.

So on Pipenv ≤ 2023.10.24, a project with a ./.venv and either variable set gets the wrong venv patched.

Impact

This is the same shape of regression as #529, which was the auto-detected .venv on 2018–2026.1. #529's fix returns both venvs when nothing explicit is set, but the explicit-false arm still returns WORKON_HOME only.

Repro

Linux, CPython 3.11 (3.8 for 2018.11.26), main 045d7ec. The patch API is a local mock serving a patched six 1.16.0 (batch / view / blob routes, SOCKET_PROXY_URL=http://127.0.0.1:8765). Any agent-mode patch for a package in the project shows the same thing.

export WORKON_HOME=$PWD/venvs
mkdir p && cd p
printf '[[source]]\nurl = "https://pypi.org/simple"\nverify_ssl = true\nname = "pypi"\n\n[packages]\nsix = "==1.16.0"\n' > Pipfile
pipenv install                               # venv under $WORKON_HOME
PIPENV_VENV_IN_PROJECT=1 pipenv sync         # ./.venv venv (e.g. a CI cache or an earlier setting)
export PIPENV_VENV_IN_PROJECT=0              # or PIPENV_NO_VENV_IN_PROJECT=1
pipenv --venv                                # 2022.12.19: …/p/.venv
socket-patch scan --mode agent --yes         # Summary: 1 of 1 targeted patch applied …  (exit 0)
grep -c SOCKET_PATCHED .venv/lib/python3*/site-packages/six.py           # 0  <- the venv Pipenv uses
grep -c SOCKET_PATCHED $WORKON_HOME/p-*/lib/python3*/site-packages/six.py # 1
pipenv run python -c "import six; print(hasattr(six,'SOCKET_PATCHED'))"  # False
socket-patch vex --product pkg:pypi/x@1 --output vex.json                 # status not_affected  <- false

Expected vs actual

OS × version (Linux, agent mode, .venv + WORKON venv, each cell run twice unless noted)

Pipenv setting pipenv --venv .venv WORKON pipenv run vex result
2018.11.26 PIPENV_VENV_IN_PROJECT=0 .venv unpatched patched unpatched not_affected fail
2018.11.26 PIPENV_NO_VENV_IN_PROJECT=1 (1×) .venv unpatched patched unpatched not_affected fail
2022.12.19 PIPENV_VENV_IN_PROJECT=0 .venv unpatched patched unpatched not_affected fail
2022.12.19 PIPENV_NO_VENV_IN_PROJECT=1 (1×) .venv unpatched patched unpatched not_affected fail
2023.10.24 PIPENV_VENV_IN_PROJECT=0 (1×) .venv unpatched patched unpatched not_affected fail
2023.10.24 PIPENV_VENV_IN_PROJECT=false (1×) .venv unpatched patched unpatched not_affected fail
2023.10.24 PIPENV_NO_VENV_IN_PROJECT=1 (1×) .venv unpatched patched unpatched not_affected fail
2023.11.14 PIPENV_VENV_IN_PROJECT=0 WORKON unpatched patched patched not_affected pass
2023.12.1 PIPENV_VENV_IN_PROJECT=0 WORKON unpatched patched patched not_affected pass
2026.8.0 PIPENV_VENV_IN_PROJECT=0 / PIPENV_NO_VENV_IN_PROJECT=1 WORKON unpatched patched patched not_affected pass
2018.11.26 / 2022.12.19 PIPENV_VENV_IN_PROJECT=0, no WORKON venv .venv unpatched n/a unpatched — fail: the global interpreter's six was patched (#504 shape)

The Pipenv boundary comes from the upstream wheels: get_location_for_virtualenv returns an existing .venv directory unconditionally in 2023.2.4, 2023.6.26, 2023.10.3, 2023.10.20 and 2023.10.24. It gates on is_venv_in_project() from 2023.11.14 on (also checked 2023.11.15, 2023.11.17, 2023.12.0 and 2023.12.1). macOS and Windows weren't probed, but this is a pure discovery decision with no OS-specific code.

First bad

Suspect code

  • crates/socket-patch-core/src/crawlers/python_crawler.rs:697 (the doc comment's "Pipenv 2023+ ignores ./.venv then") and :717-724 in pipenv_project_site_packages: if in_project.is_none() { results.extend(in_tree); } drops ./.venv for Some(false).
  • crates/socket-patch-core/src/crawlers/python_crawler.rs test pipenv_venv_in_project_settings_decide_about_dot_venv pins the 2023.11.14+ behaviour as the only one.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions