Repository navigation
Vendored PDM < 2.11 gives no stale-install warning, so after pdm sync the unpatched release stays installed while vex attests not_affected #641
Description
Activity
- addedbugSomething isn't workingSomething isn't workingbughuntFound by a scheduled package-manager bug-hunt agentFound by a scheduled package-manager bug-hunt agentpm:pdmPDMPDM
on Oct 3, 2026 - added a commit that references this issue
on Oct 3, 2026 mikolalysenko commented
on Oct 3, 2026 CollaboratorAuthorMore actions[agent] Triage: priority:p1 (PDM). This is a correctness bug, because VEX attests
not_affectedwhile the installed bytes are still unpatched. The vendored PDM flavor never calls the installed-byte stale probe (pipenv_stale_install_warningis wired only into the Pipenv flavor), and it has no counterpart to hosted'sredirect_pdm_stale_install_riskfor lock_version 2, 4.3 or 4.4. I found no duplicate. It's related to #477 (the rollback direction) but has a separate cause.
Generated by Claude Code
mikolalysenko commented
on Oct 3, 2026 CollaboratorAuthorMore actions[agent] New information from the PDM bug-hunt routine (ledger #312), on main
045d7ec, Linux, real PDM, local mock patch API. Each cell was run twice.1. PEP 582
__pypackages__hits this too. I used PDM 1.4.5 (legacy[tool.pdm]) and 1.5.3 ([project]) withuse_venv = falseand lock_version 2. I ranpdm sync(urllib3 1.26.18 lands in__pypackages__/3.8/lib), thenscan --mode vendored --yes. The scan exits 0 with no stale-install warning; the only warning isPDM 0.x may regenerate freshly generated locks during install. After that,pdm syncexits 0 and leaves__pypackages__/3.8/lib/urllib3/_version.pyunpatched.vexexits 0 and attestsnot_affected, adding only the genericvendored_tree_out_of_synchint. So VEX does see the__pypackages__tree; it just has no PDM-specific remedy.2. The remedy depends on the PDM version, and the hint's "re-run your package manager's install" doesn't work on any of these:
PDM lock_version pdm syncafter vendored scanpdm sync --reinstall1.4.5 2 unpatched no such flag ( unrecognized arguments: --reinstall). Deleting__pypackages__/3.8/lib/urllib3*and runningpdm syncinstalls the patched wheel1.5.3 2 unpatched no such flag 2.8.2 4.3 unpatched patched, lock --checkok2.10.4 4.4 unpatched patched, lock --checkok1.8.5 / 1.12.8 / 2.0.3 3 / 3.1 / 4.0 refused (documented) — So a fix that adds a warning should probably say
pdm sync --reinstallon PDM 2.x before 2.11. On PDM 1.x (lock_version 2) it should say to remove the installed package and re-sync, because--reinstalldoesn't exist there.Minor: the "PDM 0.x may regenerate…" warning also fires on locks that PDM 1.4.5 and 1.5.3 generated. Both write lock_version 2, so the heuristic can't tell them apart. It's harmless.
Generated by Claude Code
mikolalysenko commented
on Oct 3, 2026 CollaboratorAuthorMore actions[agent] Re-triage after the new data: priority:p1 stays. The scope now covers PEP 582
__pypackages__, and the remedy has to depend on the version:pdm sync --reinstallon PDM 2.x before 2.11, and remove-then-pdm syncon PDM 1.x / lock_version 2, which has no--reinstall. The root cause hasn't changed: the vendored PDM flavor has no stale-install probe. It's still unclaimed and eligible.
Generated by Claude Code
mikolalysenko commented
on Oct 9, 2026 CollaboratorAuthorMore actionsv5 triage: P2, not a release blocker. Retain the pre-PDM-2.11 stale-install warning at P2; current toolchains and the general reinstall guidance in #477 take precedence.
This follows the maintainer's release scope: one normally completing CLI instance, prioritizing valid-lockfile patch/install behavior, compatibility, and actionable CLI UX.
[agent] Found by the scheduled PDM bug-hunt routine (ledger #312).
Summary
PDM releases before 2.11 (
lock_version2/4.3/4.4) don't replace a package that's already installed at the same version. Hosted mode handles this: it emitsredirect_pdm_stale_install_risk(plus the installed-byte proberedirect_pypi_stale_install), andvexthen fails closed. Vendored mode handles neither.scan --mode vendoredon a warm PDM env exits 0 with no stale warning. The nextpdm sync/pdm installexits 0 but keeps the upstream bytes, andsocket-patch vexattestsnot_affected.The VEX envelope does carry a
vendored_tree_out_of_syncwarning, but its advice ("re-run your package manager's install to resync it") doesn't work on these PDM versions:pdm syncis exactly the step that keeps the old bytes.Impact
A team on PDM 1.x / 2.0–2.10 vendors a patch into a project where the dependency is already installed (a dev machine, a cached CI venv) and runs
pdm sync. Every command succeeds, yet the vulnerable code keeps running, and the published VEX says the vulnerability is mitigated. Hosted mode warns about this exact PDM behaviour, so vendored users get a weaker guarantee for the same lock.Repro
Uses a local mock of the patch API that serves a patched urllib3 1.26.18 wheel, with a marker line appended to
urllib3/response.py. Any free urllib3 1.26.18 patch shows the same thing.For comparison, the same project with
--mode hostedemitsredirect_pdm_stale_install_riskandredirect_pypi_stale_install, andvexexits 1 (no_applicable_patches).Expected vs actual
docs/testing/pdm-compatibility.mdsays PDM < 2.11 keeps an already-installed same-version package, andredirect/pdm.rswarns proactively once per lock for that reason. The Pipenv vendored path already probes the installed bytes (pypi_pipenv_stale_install, documented in docs/ecosystems.md). The vendored PDM path should warn with the remedy that works (pdm sync --reinstall, uninstall the package, or recreate the env), and the VEX hint shouldn't say a plain reinstall resyncs it.pdm sync/pdm installleave the env unpatched, andvexattestsnot_affectedwith only the genericvendored_tree_out_of_synchint.Matrix (Linux, main
045d7ec, real PDM)pdm syncpypi_pdm_legacy_sync_required)pypi_pdm_legacy_sync_required)pdm syncandpdm install; reproduced twice)--mode hosted(control)redirect_pdm_stale_install_risk,redirect_pypi_stale_install)macOS and Windows weren't probed. The behaviour comes from PDM's installer, not the OS.
Suspect code
crates/socket-patch-core/src/vendor/pypi_pdm.rs:95-97only addspypi_pdm_legacy_sync_requiredforlock_version == "2". There's no equivalent of the hostedredirect_pdm_stale_install_riskfor 2 / 4.3 / 4.4.crates/socket-patch-core/src/vendor/pypi.rs:606(pipenv_stale_install_warning) is only called from the Pipenv flavor (pypi.rs:881), so the PDM flavor never probes the installed bytes.crates/socket-patch-core/src/patch/redirect/pdm.rs:42-55is the hosted counterpart to mirror.crates/socket-patch-cli/src/commands/vex.rs:677-690is thevendored_tree_out_of_syncadvice.Related but distinct: #477 (the reverse direction, after rollback).