Skip to content

vendor --check says "committed artifact and wiring verified" (exit 0) after pipenv lock drops the vendored reference, so a fresh pipenv install --deploy installs the unpatched wheel while vex says vendor_unwired #725

Description

[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).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions