Vendored scan of a Pipenv `use_pylock = true` project wires only pylock.toml, but Pipenv installs from Pipfile.lock, so `pipenv sync` / `install --deploy` install the unpatched release after a "success" run
Les mainteneurs répondent en général sous 1 jour
Une pull request liée a déjà été fusionnée.
- #1193 par @mikolalysenko — fusionnée
Évaluation
- Difficulté
- 2/5
- Temps estimé
- Moins d'une heure
- Accessibilité débutants
- 85/100
Piste de recherche
Le bug se trouve dans la logique de détection de variante PyPI. Commencez dans crates/socket-patch-core/src/vendor/pypi.rs vers la ligne 251 et dans crates/socket-patch-core/src/formats/governing_locks.rs vers la ligne 115. Ajustez le classement des fichiers de verrouillage afin que, lorsqu’un Pipfile est présent avec à la fois Pipfile.lock et pylock.toml, l’outil sélectionne Pipfile.lock comme fichier de verrouillage faisant autorité (ou relie les deux). Exécutez les tests pertinents pour confirmer la correction.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
[agent] Found by the scheduled Pipenv bug-hunt routine (ledger #313).
Summary
With [pipenv] use_pylock = true in the Pipfile, Pipenv 2026's pipenv lock writes both Pipfile.lock and pylock.toml. The pylock.toml carries [tool.pipenv] generated_from = "Pipfile.lock". When both files are present, Pipenv installs from Pipfile.lock: pipenv sync and pipenv install --deploy take the bytes from Pipfile.lock and ignore pylock.toml. I verified this below on 2026.0.0, 2026.4.0 and 2026.8.0.
scan --mode vendored routes this layout to the standalone python-lock flavor, because detect_pypi_flavor step 2 (a standalone pylock*.toml that contains the package) ranks above step 5 (Pipfile.lock → pipenv). So it rewrites only pylock.toml (archive = { path = ".socket/vendor/pypi/<uuid>/…whl" }) and leaves Pipfile.lock on PyPI. The run reports status: success, exit 0, "Vendored 1 package". Its only warning is pypi_multiple_lockfiles: "wiring pylock.toml; installs driven by Pipfile.lock retain their existing sources".
So every Pipenv install afterwards puts the unpatched upstream release in place. Hosted mode handles the same layout correctly: it pins both files, and pipenv sync gives the patched bytes.
This is distinct from #912. #912 is the pylock-only checkout, where Pipenv reads pylock.toml and drops archive. #912 already notes that with both files present "Pipenv installs from Pipfile.lock", which is exactly why vendoring the pylock alone misses here.
Impact
- The documented
use_pylock = truelayout, vendored, never gets the patch in any Pipenv install (CI, Docker,--deploy), although the scan says it vendored the package. - The user-visible remedy is awkward.
vendor --check(exit 1) says to delete whichever lock the project doesn't install from, butpipenv lockregeneratespylock.tomlwhileuse_pylock = trueis set, and the next vendored run wires it again. vexrefuses, as it should (pkg:pypi/[email protected] is wired … but Pipfile.lock resolves the same version from elsewhere, exit 1). So there's no false attestation. The defect is that the wrong file is chosen as the governing lock.
Repro (Linux; real Pipenv 2026.8.0, py3.11; local mock patch API serving a patched six 1.16.0 wheel)
mkdir app && cd app
cat > Pipfile <<'EOF'
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
six = "==1.16.0"
[requires]
python_version = "3.11"
[pipenv]
use_pylock = true
EOF
pipenv lock # writes Pipfile.lock AND pylock.toml
socket-patch scan --mode vendored --yes # exit 0, "Vendored 1 package."
# Warning: wiring pylock.toml; installs driven by Pipfile.lock retain their existing sources
grep -c socket/vendor Pipfile.lock # 0
grep -c socket/vendor pylock.toml # 1
pipenv --rm; pipenv install --deploy
pipenv run python -c "import six; print('SOCKET-PATCHED' in open(six.__file__).read())" # False
pipenv --rm; pipenv sync # same: False
socket-patch vendor --check # exit 1: wiring contested
socket-patch vex --offline --product pkg:pypi/[email protected] -O vex.json # exit 1, refuses
# Control: the same project, hosted
socket-patch scan --mode hosted --yes # rewrittenFiles: [Pipfile.lock, pylock.toml]
pipenv --rm; pipenv sync # patched
# Which file Pipenv reads: hosted Pipfile.lock + pristine pylock.toml -> sync / --deploy give the PATCHED bytes
scan --mode vendored --dry-run previews the same pylock-only wiring. Reproduced 2/2 on 2026.8.0, plus once each on 2026.0.0 and 2026.4.0.
Expected vs actual
- Expected: vendored wires the file the project's installer reads. When a
Pipfilesits beside both locks (and pylock.toml saysgenerated_from = "Pipfile.lock"), that'sPipfile.lock. The flavor router's own doc says it routes by "this tool manages installs". docs/ecosystems.md lists PipenvPipfile.lockvendoring as supported ("everyPipfile.lockcategory is rewired"). It would also be reasonable to wire both files, as hosted mode does. CLI_CONTRACT.md: "A dep counts as redirected only when its hosted-artifact URL … actually landed in a project file". The vendored analogue is a rewrite the installer honours. - Actual: only
pylock.tomlis wired, and Pipenv ignores it whilePipfile.lockexists. The scan succeeds, and every Pipenv install is unpatched.
OS × version
| Pipenv | both locks written by pipenv lock |
vendored wires | pipenv sync / --deploy after vendored |
control: hosted Pipfile.lock + pristine pylock.toml |
|---|---|---|---|---|
| 2026.0.0 | yes | pylock.toml only | UPSTREAM | PATCHED |
| 2026.4.0 | yes | pylock.toml only | UPSTREAM | PATCHED |
| 2026.8.0 | yes | pylock.toml only (2/2) | UPSTREAM (sync and --deploy) |
PATCHED |
| ≤ 2025.x | n/a (no pylock support) | |||
| macOS / Windows | not probed (the routing is pure path-presence logic) |
First bad version
Not bisected. v4.0.0 has no pylock vendoring, so this is unreleased v5 behaviour on main b96a785. #1044 moved the tool-lock order into formats/governing_locks.rs (PYPI_TOOL_LOCKS), but the standalone-lock branch that wins here sits before that table and predates it.
Suspect code
crates/socket-patch-core/src/vendor/pypi.rs:251(doc, step 2) and:310–:324:if !has_uv_lock && matching_additional_lock { … return Ok((PypiFlavor::PythonLocks, warnings)) }. Any standalone pylock that contains the package beatsPipfile.lock, and nothing checks for aPipfileor a[tool.pipenv]table in the pylock.crates/socket-patch-core/src/formats/governing_locks.rs:115:PYPI_TOOL_LOCKSdoesn't place Pipenv-generated pylocks relative toPipfile.lock.
Related: #912 (pylock-only Pipenv checkout; Pipenv drops archive), #612 (pypi_multiple_lockfiles for a sibling requirements.txt), #1114 (inventory vs router disagreement on empty poetry / pdm locks).
- Langage dominant
- Rust
- Étoiles
- 8
- Forks
- 0
- Merge moyen
- 19 h 21 min
- PR mergées (30 j)
- 421
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Aucun modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de SocketDev/socket-patch
-
agent:triaged bug bughunt pm:npm priority:p3
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
SocketDev/socket-patch#1072 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
Hosted gem `rollback` / `remove` strips the `DEPENDENCIES` `!` of a gem the user declared inside a `source "https://rubygems.org" do` block, so every frozen install fails after the unwindPeut-être pris @mikolalysenko l’a pris il y a 1 jour. Ouverteagent:triaged bug bughunt pm:bundler priority:p1
Difficulté 2/5 1-3 heures Accessibilité débutants 80/100
SocketDev/socket-patch#1056 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
agent:triaged bug bughunt pm:bundler priority:p1
Difficulté 2/5 1-3 heures Accessibilité débutants 85/100
SocketDev/socket-patch#896 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
agent:triaged bug bughunt pm:yarn-berry priority:p1
Difficulté 2/5 1-3 heures Accessibilité débutants 73/100
SocketDev/socket-patch#783 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
agent:triaged bug bughunt pm:cargo priority:p2
Difficulté 2/5 1-3 heures Accessibilité débutants 84/100
SocketDev/socket-patch#651 · 3 commentaires ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de SocketDev/socket-patch
Issues similaires
-
[Bug]: Web chat input doesn't regain focus after a reply finishesPeut-être pris @GaijinSystems l’a pris aujourd’hui. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100
zeroclaw-labs/zeroclaw#11658 ·
Les mainteneurs répondent en général sous 2 jours
-
good first issue help wanted
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
-
documentation
Difficulté 2/5 1-3 heures Accessibilité débutants 70/100
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 62/100
NuSkooler/enigma-bbs#907 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
Les mainteneurs répondent en général sous 1 jour