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
Mantenedores costumam responder em até 1 dia
Um pull request relacionado já foi integrado.
- #1193 de @mikolalysenko — integrado
Avaliação
- Dificuldade
- 2/5
- Tempo estimado
- Menos de uma hora
- Facilidade para iniciantes
- 85/100
Direção de pesquisa
O bug está na lógica de detecção de variantes do PyPI. Comece em crates/socket-patch-core/src/vendor/pypi.rs, por volta da linha 251, e em crates/socket-patch-core/src/formats/governing_locks.rs, por volta da linha 115. Ajuste a classificação dos arquivos de lock para que, quando houver um Pipfile junto com Pipfile.lock e pylock.toml, a ferramenta selecione Pipfile.lock como o arquivo de lock governante (ou conecte ambos). Execute os testes relevantes para confirmar a correção.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
[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).
- Linguagem predominante
- Rust
- Estrelas
- 8
- Forks
- 0
- Merge médio
- 19h 21min
- PRs com merge (30d)
- 421
Preparar o ambiente
- Sem Dockerfile nem arquivo Docker Compose
- Sem modelo de pull request
- Ler o guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de SocketDev/socket-patch
-
agent:triaged bug bughunt pm:npm priority:p3
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 75/100
SocketDev/socket-patch#1072 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
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 unwindTalvez já em andamento @mikolalysenko assumiu há 1 dia. Abertaagent:triaged bug bughunt pm:bundler priority:p1
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 80/100
SocketDev/socket-patch#1056 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
agent:triaged bug bughunt pm:bundler priority:p1
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 85/100
SocketDev/socket-patch#896 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
agent:triaged bug bughunt pm:yarn-berry priority:p1
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 73/100
SocketDev/socket-patch#783 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
agent:triaged bug bughunt pm:cargo priority:p2
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 84/100
SocketDev/socket-patch#651 · 3 comentários ·
Mantenedores costumam responder em até 1 dia
Todas as issues de SocketDev/socket-patch
Issues semelhantes
-
XmlFragment children, successors and siblings stop at the first child that is not an XML typeAberta
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 72/100
Mantenedores costumam responder em até 1 dia
-
bug good first issue
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 84/100
repowise-dev/repowise#3374 ·
Mantenedores costumam responder em até 1 dia
-
awaiting-response bug needs-triage
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 72/100
wildcard/caro#1562 · 1 comentário ·
Mantenedores costumam responder em até 3 dias
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 75/100
objectionary/sodg.rs#301 ·
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 62/100
HakanSeven12/OpenCADStudio#1706 · 1 comentário ·
Mantenedores costumam responder em até 1 dia