You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
With {data-dir} in Poetry's virtualenvs.path, agent mode also patches an unrelated activated VIRTUAL_ENV / conda env, even though poetry env use pins the project's env, and hosted VEX then refuses a correctly installed patch #866
[agent] Found by the scheduled Poetry bug-hunt routine (ledger #311).
Summary
Since #644 (the fix for #608 / #640), Poetry venv discovery builds one "placement" per Poetry placeholder generation (Current, NoDataDir, Poetry11) and unions the results. With the default {cache-dir}/virtualenvs path, the three placements collapse into one root. With virtualenvs.path = "{data-dir}/venvs", they become three different roots:
~/.local/share/pypoetry/venvs
<project>/{data-dir}/venvs
/venvs
poetry_active_prefix is checked per placement. The poetry env use record (envs.toml) lives in only one of those roots, so the other placements have no activation record and fall back to VIRTUAL_ENV / a non-base CONDA_PREFIX. Poetry itself (EnvManager.get) ignores VIRTUAL_ENV when envs.toml has an entry for the project. socket-patch patches the project's env and whatever unrelated venv or conda env happens to be active in the shell.
Impact
Agent mode writes into an environment Poetry doesn't use for this project. For example, another project's activated .venv, or a conda work env. That environment's own project has no manifest entry for the change.
VEX now depends on the unrelated env's state. After the unrelated env is reinstalled, socket-patch vex for the project omits the patch (not_applied) even though the project's own env is still patched.
Hosted: after a correct scan --mode hosted and poetry install (the project env holds the patched wheel), socket-patch vex refuses the patch (not_applied, "No applied patches…") whenever an unrelated venv is active. This is a false negative caused by the shell's state.
Repro (Linux, real Poetry 2.5.1 and 1.8.5, CPython 3.11 + 3.12)
The patch API is a local mock serving one six.py patch for pkg:pypi/six@1.16.0 (the same routes as tests/vex_pypi_real_common). HOME is a fresh directory.
Patched packages:
pkg:pypi/six@1.16.0 (~/.local/share/pypoetry/venvs/demo-_l0efc1a-py3.12/lib/python3.12/site-packages, via blob)
pkg:pypi/six@1.16.0 (/tmp/other/lib/python3.11/site-packages, via blob)
proj=1 other=1
Hosted variant (same project and env, no agent patch):
unset VIRTUAL_ENV
socket-patch scan --mode hosted --yes --ecosystems pypi && poetry install # project env gets the patched wheel
socket-patch vex -O v1.json # not_affected (correct)
VIRTUAL_ENV=/tmp/other socket-patch vex -O v2.json
# Warning: omitting pkg:pypi/six@1.16.0 from VEX: the patched files still hold the original content (not_applied)# Error: No applied patches with vulnerability metadata to attest.
Expected vs actual
Expected: discovery mirrors EnvManager.get(). When the project has an envs.toml record, that env is the only one Poetry uses, and VIRTUAL_ENV / CONDA_PREFIX are ignored. The crawler's own doc comment on poetry_active_prefix says so ("only when this placement has no poetry env use record"), and Fix Poetry venv selection ignoring envs.toml (#476, #526) #527 fixed exactly this for the single-root case. With {data-dir}, the placements other than the one that resolved the record shouldn't bring the active shell env back in. docs/testing/poetry-compatibility.md describes agent mode as patching "the env Poetry installed into".
Actual: the active shell env is patched alongside the project env, and VEX judges both.
Matrix (Linux, main 99f61d2)
Poetry
virtualenvs.path
env use record
Active env
Project env
Unrelated env
Hosted vex
2.5.1
{data-dir}/venvs
yes
VIRTUAL_ENV=/tmp/other
patched
patched ❌
refuses ❌
2.5.1
{data-dir}/venvs
yes
CONDA_PREFIX=/tmp/other, CONDA_DEFAULT_ENV=work
patched
patched ❌
not run
1.8.5
{data-dir}/venvs (literal in 1.8)
yes
VIRTUAL_ENV=/tmp/other
patched
patched ❌; vex omits after /tmp/other reinstall
not run
2.5.1
default
yes
VIRTUAL_ENV=/tmp/other
patched
untouched ✅
attests ✅ (control)
Each failing cell reproduced at least twice. macOS and Windows weren't tested, because this routine's probe branches are blocked. On macOS, poetry_default_data_dirs can also return two data dirs (XDG + Library), so I'd expect the same split there.
First bad commit
This isn't a clean regression. On 22157a54^ (just before #644), the same 2.5.1 layout patched only/tmp/other and not the project env (2/2), which was the #608 / {data-dir} miss. #644 added the project env but kept the unrelated one, so the leftover over-patch dates from #644 (22157a54).
Suspect code
crates/socket-patch-core/src/crawlers/python_crawler.rs:1460-1463 (poetry_project_site_packages): runs poetry_active_prefix(placement, var) for each placement independently, then unions the results.
crates/socket-patch-core/src/crawlers/python_crawler.rs:1317 (poetry_active_prefix): only vetoes the active env when this placement has an activation record. An activation in any placement should veto it for every placement, or placements should be deduplicated to the ones that are reachable.
crates/socket-patch-core/src/crawlers/python_crawler.rs:1054 (poetry_virtualenvs_paths): the NoDataDir / Poetry11 generations turn {data-dir}/venvs into <cwd>/{data-dir}/venvs and /venvs.
Related
#608 / #640 (closed by #644), #527 (the single-root VIRTUAL_ENV + envs.toml fix), #671.
[agent] Found by the scheduled Poetry bug-hunt routine (ledger #311).
Summary
Since #644 (the fix for #608 / #640), Poetry venv discovery builds one "placement" per Poetry placeholder generation (
Current,NoDataDir,Poetry11) and unions the results. With the default{cache-dir}/virtualenvspath, the three placements collapse into one root. Withvirtualenvs.path = "{data-dir}/venvs", they become three different roots:~/.local/share/pypoetry/venvs<project>/{data-dir}/venvs/venvspoetry_active_prefixis checked per placement. Thepoetry env userecord (envs.toml) lives in only one of those roots, so the other placements have no activation record and fall back toVIRTUAL_ENV/ a non-baseCONDA_PREFIX. Poetry itself (EnvManager.get) ignoresVIRTUAL_ENVwhenenvs.tomlhas an entry for the project. socket-patch patches the project's env and whatever unrelated venv or conda env happens to be active in the shell.Impact
.venv, or a conda work env. That environment's own project has no manifest entry for the change.socket-patch vexfor the project omits the patch (not_applied) even though the project's own env is still patched.scan --mode hostedandpoetry install(the project env holds the patched wheel),socket-patch vexrefuses the patch (not_applied, "No applied patches…") whenever an unrelated venv is active. This is a false negative caused by the shell's state.Repro (Linux, real Poetry 2.5.1 and 1.8.5, CPython 3.11 + 3.12)
The patch API is a local mock serving one
six.pypatch forpkg:pypi/six@1.16.0(the same routes astests/vex_pypi_real_common).HOMEis a fresh directory.Actual (2.5.1):
Hosted variant (same project and env, no agent patch):
Expected vs actual
EnvManager.get(). When the project has anenvs.tomlrecord, that env is the only one Poetry uses, andVIRTUAL_ENV/CONDA_PREFIXare ignored. The crawler's own doc comment onpoetry_active_prefixsays so ("only when this placement has nopoetry env userecord"), and Fix Poetry venv selection ignoring envs.toml (#476, #526) #527 fixed exactly this for the single-root case. With{data-dir}, the placements other than the one that resolved the record shouldn't bring the active shell env back in. docs/testing/poetry-compatibility.md describes agent mode as patching "the env Poetry installed into".Matrix (Linux, main
99f61d2)virtualenvs.pathenv userecordvex{data-dir}/venvsVIRTUAL_ENV=/tmp/other{data-dir}/venvsCONDA_PREFIX=/tmp/other,CONDA_DEFAULT_ENV=work{data-dir}/venvs(literal in 1.8)VIRTUAL_ENV=/tmp/othervexomits after/tmp/otherreinstallVIRTUAL_ENV=/tmp/otherEach failing cell reproduced at least twice. macOS and Windows weren't tested, because this routine's probe branches are blocked. On macOS,
poetry_default_data_dirscan also return two data dirs (XDG + Library), so I'd expect the same split there.First bad commit
This isn't a clean regression. On
22157a54^(just before #644), the same 2.5.1 layout patched only/tmp/otherand not the project env (2/2), which was the #608 /{data-dir}miss. #644 added the project env but kept the unrelated one, so the leftover over-patch dates from #644 (22157a54).Suspect code
crates/socket-patch-core/src/crawlers/python_crawler.rs:1460-1463(poetry_project_site_packages): runspoetry_active_prefix(placement, var)for each placement independently, then unions the results.crates/socket-patch-core/src/crawlers/python_crawler.rs:1317(poetry_active_prefix): only vetoes the active env when this placement has an activation record. An activation in any placement should veto it for every placement, or placements should be deduplicated to the ones that are reachable.crates/socket-patch-core/src/crawlers/python_crawler.rs:1054(poetry_virtualenvs_paths): theNoDataDir/Poetry11generations turn{data-dir}/venvsinto<cwd>/{data-dir}/venvsand/venvs.Related
#608 / #640 (closed by #644), #527 (the single-root
VIRTUAL_ENV+envs.tomlfix), #671.