[agent] Found by the scheduled Pipenv bug-hunt routine (ledger #313).
Summary
socket-patch vendor --check is documented as an "offline, read-only artifact and wiring audit; exits 1 on drift" (CLI_CONTRACT.md, vendor --check row). For a vendored Pipenv project it only checks the committed wheel. If Pipfile.lock no longer references .socket/vendor/..., it still prints committed artifact and wiring verified (vendor_check_ok) and exits 0.
The common way to get there is pipenv lock (or pipenv update, or pipenv install <other> before 2024). docs/testing/pipenv-compatibility.md says this "regenerates the redirected entry to its registry reference on every major, hosted and vendored — a silent unpatch". vendor --check is the CI gate that should catch that silent unpatch, and it reports green instead. On the same checkout, vex correctly refuses with vendor_unwired, so the two commands disagree.
Impact
A CI job that runs socket-patch vendor --check passes on a commit whose Pipfile.lock installs the unpatched upstream wheel on every fresh pipenv sync / pipenv install --deploy.
Repro (Linux, main 045d7ec, real Pipenv)
Patch data comes from a local mock of the patch API (batch / by-package / view / blob), plus a SOCKET_PYPI_JSON_API forwarder that serves the upstream six 1.16.0 wheel. The mock's patch adds SOCKET_PATCHED = 1 to six.py.
cat > Pipfile <<'EOF'
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[packages]
six = "==1.16.0"
EOF
pipenv lock
socket-patch get pkg:pypi/six@1.16.0 --mode vendored --yes # exit 0; Pipfile.lock -> "file": "./.socket/vendor/pypi/<uuid>/six-1.16.0-py2.py3-none-any.whl"
grep -c socket/vendor Pipfile.lock # 1
pipenv lock # relock: entry back to the registry reference
grep -c socket/vendor Pipfile.lock # 0
rm -rf .venv && pipenv install --deploy
pipenv run python -c "import six; print(getattr(six,'SOCKET_PATCHED',0))" # 0 -> UNPATCHED
socket-patch vendor --check; echo $?
# pkg:pypi/six@1.16.0: committed artifact and wiring verified
# 0
socket-patch vendor --check --json # status "success", events[0] = {action: "verified", errorCode: "vendor_check_ok"}
socket-patch vex --product pkg:pypi/demo@1.0.0 --offline -O vex.json; echo $?
# Warning: omitting pkg:pypi/six@1.16.0 from VEX: ... no lockfile or config wires it to this package any more (vendor_unwired)
# 1
Expected vs actual
- Expected:
vendor --check reports failed / vendor_check_failed with partialFailure and exit 1, because the ledger records wiring that Pipfile.lock no longer carries (CLI_CONTRACT.md: "drift emits failed with vendor_check_failed, a partialFailure envelope and exit 1"). The CLI already has the probe it needs: the "lockfile in-use probe" that scan uses for vendor_ledger_entry_unwired, and the one vex uses for vendor_unwired.
- Actual:
verified / vendor_check_ok, exit 0.
Matrix (Linux; each row run in a fresh project)
| Pipenv |
relock drops the ref |
fresh install --deploy |
vendor --check |
vex |
| 2018.11.26 (py3.8) |
yes |
UNPATCHED |
exit 0, "wiring verified" |
exit 1 vendor_unwired |
| 2022.12.19 |
yes |
UNPATCHED |
exit 0, "wiring verified" |
exit 1 vendor_unwired |
| 2023.12.1 |
yes |
UNPATCHED |
exit 0, "wiring verified" |
exit 1 vendor_unwired |
| 2026.8.0 (reproduced twice) |
yes |
UNPATCHED |
exit 0, "wiring verified" |
exit 1 vendor_unwired |
macOS and Windows weren't probed (no probe branches this run). The code path isn't OS-specific.
First bad commit
vendor --check isn't in any release (v4.0.0 has no vendor_check_ok). It arrived on main in de316b4, and has behaved like this since then.
Suspect code
crates/socket-patch-cli/src/commands/vendor.rs:918-966 (run_check). For every entry it calls only vendor::check_vendored_artifact (artifact bytes and fingerprint). The wiring check at line 955 runs only for JVM entries (vendor::jvm::apply::is_jvm_entry). For PyPI entries, and every other non-JVM ecosystem, nothing compares the ledger's recorded wiring with the current lockfile, yet the event text still says "wiring verified". Other vendored lockfile ecosystems are probably affected the same way (relocking uv / poetry / pdm, or npm install), but I only reproduced it with Pipenv.
Related, but not the same: #588 (npm, a second copy left unwired while vex and --check pass) and #612 (Pipenv vendored with a sibling requirements.txt).
[agent] Found by the scheduled Pipenv bug-hunt routine (ledger #313).
Summary
socket-patch vendor --checkis documented as an "offline, read-only artifact and wiring audit; exits 1 on drift" (CLI_CONTRACT.md,vendor --checkrow). For a vendored Pipenv project it only checks the committed wheel. IfPipfile.lockno longer references.socket/vendor/..., it still printscommitted artifact and wiring verified(vendor_check_ok) and exits 0.The common way to get there is
pipenv lock(orpipenv update, orpipenv install <other>before 2024). docs/testing/pipenv-compatibility.md says this "regenerates the redirected entry to its registry reference on every major, hosted and vendored — a silent unpatch".vendor --checkis the CI gate that should catch that silent unpatch, and it reports green instead. On the same checkout,vexcorrectly refuses withvendor_unwired, so the two commands disagree.Impact
A CI job that runs
socket-patch vendor --checkpasses on a commit whosePipfile.lockinstalls the unpatched upstream wheel on every freshpipenv sync/pipenv install --deploy.Repro (Linux, main
045d7ec, real Pipenv)Patch data comes from a local mock of the patch API (batch / by-package / view / blob), plus a
SOCKET_PYPI_JSON_APIforwarder that serves the upstreamsix 1.16.0wheel. The mock's patch addsSOCKET_PATCHED = 1tosix.py.Expected vs actual
vendor --checkreportsfailed/vendor_check_failedwithpartialFailureand exit 1, because the ledger records wiring thatPipfile.lockno longer carries (CLI_CONTRACT.md: "drift emitsfailedwithvendor_check_failed, apartialFailureenvelope and exit 1"). The CLI already has the probe it needs: the "lockfile in-use probe" thatscanuses forvendor_ledger_entry_unwired, and the onevexuses forvendor_unwired.verified/vendor_check_ok, exit 0.Matrix (Linux; each row run in a fresh project)
install --deployvendor --checkvexvendor_unwiredvendor_unwiredvendor_unwiredvendor_unwiredmacOS and Windows weren't probed (no probe branches this run). The code path isn't OS-specific.
First bad commit
vendor --checkisn't in any release (v4.0.0 has novendor_check_ok). It arrived on main inde316b4, and has behaved like this since then.Suspect code
crates/socket-patch-cli/src/commands/vendor.rs:918-966(run_check). For every entry it calls onlyvendor::check_vendored_artifact(artifact bytes and fingerprint). The wiring check at line 955 runs only for JVM entries (vendor::jvm::apply::is_jvm_entry). For PyPI entries, and every other non-JVM ecosystem, nothing compares the ledger's recorded wiring with the current lockfile, yet the event text still says "wiring verified". Other vendored lockfile ecosystems are probably affected the same way (relocking uv / poetry / pdm, ornpm install), but I only reproduced it with Pipenv.Related, but not the same: #588 (npm, a second copy left unwired while vex and
--checkpass) and #612 (Pipenv vendored with a sibling requirements.txt).