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
メンテナーはふだん 1 日以内に返信
関連するプルリクエストがすでにマージされています。
- #1193 @mikolalysenko による — マージ済み
評価
- 難易度
- 2/5
- 見積もり時間
- 1時間未満
- 初心者へのやさしさ
- 85/100
調査の方向性
不具合はPyPIの種類判定ロジックにあります。crates/socket-patch-core/src/vendor/pypi.rsの251行目付近と、crates/socket-patch-core/src/formats/governing_locks.rsの115行目付近から調べてください。PipfileとともにPipfile.lockとpylock.tomlの両方が存在する場合に、ツールがPipfile.lockを基準となるロックファイルとして選択する(または両方を接続する)よう、ロックファイルの優先順位を調整してください。修正を確認するため、関連するテストを実行してください。
索引モデルが issue の本文から書いたものです。
説明
[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).
- 主要言語
- Rust
- スター
- 8
- フォーク
- 1
- 平均マージ
- 19時間 1分
- マージ済み PR(30日)
- 473
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
SocketDev/socket-patch のほかの issue
-
agent:triaged bug pm:go priority:p2
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
SocketDev/socket-patch#1409 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
agent:triaged bug bughunt pm:npm priority:p3 ux
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
SocketDev/socket-patch#1072 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
agent:triaged bug bughunt pm:yarn-berry priority:p1
難易度 2/5 1〜3時間 初心者へのやさしさ 73/100
SocketDev/socket-patch#783 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
Vendored cargo warns cargo_multi_version_old_cargo ("declares no rust-version") when the root package inherits rust-version from [workspace.package]対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープンagent:triaged bug bughunt pm:cargo priority:p2
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
SocketDev/socket-patch#651 · コメント 3 件 ·
メンテナーはふだん 1 日以内に返信
-
agent:triaged bench perf-regression pm:nuget priority:p3
難易度 4/5 3〜5日 初心者へのやさしさ 45/100
SocketDev/socket-patch#1425 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
SocketDev/socket-patch の issue をすべて見る
似ている issue
-
ai-priority/P2 bug db/oracle user-priority/P1
難易度 2/5 1〜3時間 初心者へのやさしさ 67/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
swc-project/swc#12516 ·
メンテナーはふだん 1 日以内に返信
-
app bug
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
-
mls-rs-crypto-awslc: exact aws-lc-rs =1.16.3 pin blocks rustls security update対応中かも @muscariello が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100