Skip to content

Fix bare requirements wheel paths not contesting VEX (#1587) - #1599

Open
Mikola Lysenko (mikolalysenko) wants to merge 5 commits into
mainfrom
agent/fix-requirements-bare-path-contest
Open

Mikola Lysenko (mikolalysenko) wants to merge 5 commits into
mainfrom
agent/fix-requirements-bare-path-contest

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

LLM Description written by Claude Code:claude-opus-5-5

Fixes #1587

Summary

pip installs a requirements.txt line such as wheels/six-1.16.0-py3-none-any.whl, six-1.16.0-py3-none-any.whl or dist/six-1.16.0.tar.gz as a local, unpatched artifact. Before this fix, vex ignored those lines and attested not_affected for a Socket wiring of the same release in Pipfile.lock. Only the ./wheels/… spelling was withheld (#1562). These spellings now contest the wiring the same way, so vex withholds the statement with patched_ref_unattributable.

Root cause

requirement_location (crates/socket-patch-core/src/vex/discover/pypi_other.rs) read a line as a path only when its first character wasn't a letter or digit. pip's rule (_looks_like_path / _get_url_from_path) is different: a token is a path when it holds a path separator, starts with ., or names an archive file.

Changes

  • utils::requirements, the shared requirements grammar, gets pip's rule as pip_reads_as_path, with is_archive_file (pip's ARCHIVE_EXTENSIONS, and its splitext handling of .tar.<ext>), names_before_at and strip_path_extras.
  • requirement_location uses these helpers and now also follows pip on two more points:
    • A no-space six@https://… or six@wheels/…whl is a PEP 508 reference to six. Before, the url form was read as a bare url and lost its declared name.
    • A path's [extras] are cut before its filename is read, so wheels/six-…whl[socks] also contests.

Tests (red → green)

Covers Test main this PR
#1587 wheels/…whl, …whl, dist/…tar.gz, wheels\…whl, path with a ; marker, vendored Pipfile.lock wiring vex::discover::pypi_other::tests::issue_1549_non_socket_direct_references_contest_wiring (new cases) FAILED ok
#1587 parser vex::discover::pypi_other::tests::issue_1587_requirement_location_reads_paths_as_pip_does FAILED (left: None) ok
#1587 shared rule utils::requirements::tests::pip_reads_as_path_follows_pip (new helper) ok
#1587 real CLI vex, hosted and vendored wiring e2e_vex_lockfile pipenv::requirements_direct_reference_contests_the_lock_wiring (the issue's three spellings) FAILED (vex exit 0) ok

The red runs used main's pypi_other.rs with the new e2e cases in place.

Local runs:

  • cargo fmt --all -- --check: clean
  • cargo clippy --workspace --all-features -- -D warnings: clean
  • cargo test -p socket-patch-core --lib: 6536 passed, 4 failed. The 4 are chmod-based tests that can't fail under uid 0 in this sandbox: relax_loop_must_not_traverse_symlinked_root, an_unremovable_hidden_lock_keeps_every_store_entry, and the poetry and requirements write-failure tests. Other agent PRs report the same 4 on main.
  • e2e_vex_lockfile: 350 passed
  • e2e_vex_redirect (53), e2e_vex_vendor (52), in_process_redirect_pipenv (11), in_process_vendor_pypi_takeover (6), scan_requirements_lock_only (10) and scan_vendor_requirements_unwired (4): all pass
  • npm/pypi/gem wrappers: not touched, since they only dispatch the binary

CI and Bugbot

Merge queue (2026-10-20): dequeued on the pipenv pylock leg, a main-wide break from uv 0.13.2+ (also fails main nightly, #1605, #1614). Ported #1639's uv 0.13.1 pin in 29877b3 after merging main; CI green there, pipenv leg included.

CI on 3a4de37: ci-ok green, no failed checks. Bugbot reviewed 3a4de37 and found no issues.

/code-review high

Fixed in 3a4de37:

  • six@https://… lost its declared name.
  • [extras] on a path hid its filename.
  • The archive test didn't split .tar.<ext> the way pip does.
  • The rule lived privately in VEX discovery. It now sits in the shared requirements grammar.

Not changed:

  • Rare archive suffixes pip accepts (.tar, .tbz, .txz, .tlz, .tar.lz, .tar.lzma) are now read as paths. The release can't be read from those filenames, though, so they still give no evidence, as before this PR. Real sdists use .tar.gz or .zip (PEP 625 requires .tar.gz). Widening the filename reader would also change the hosted rewriter and the lock inventory.
  • Hosted/vendored requirements writers: requirement_name still reads a bare path line as a name (wheels). These writers don't attest anything. Whether they should treat such a line as an install source of the package is a separate change, left as a follow-up.

https://claude.ai/code/session_01JM7idHTBGCQp9fzoGJviT3


Note

Medium Risk
Changes VEX contesting logic for requirements.txt parsing, which affects attestation outcomes when alternate install sources coexist with lock wiring; scope is localized to PyPI/VEX discovery with broad test coverage.

Overview
Fixes #1587: VEX discovery now treats requirements.txt lines that pip installs as local artifacts—e.g. wheels/six-….whl, bare wheel filenames, and dist/….tar.gz—as install sources that contest Socket wiring in Pipfile.lock, instead of only recognizing ./wheels/….

The shared requirements grammar gains pip-aligned helpers (pip_reads_as_path, names_before_at, strip_path_extras, is_archive_file), and requirement_location uses them so no-space name@url / name@path PEP 508 references keep a declared name and path [extras] are stripped before reading the location.

CI pins uv 0.13.1 in ci.yml and pipenv-compatibility.yml because uv 0.13.2+ rejects Pipenv’s empty-environments pylock used in PEP 751 test legs.

Unit, discovery, and Pipenv e2e tests cover the new spellings and parser behavior.

Reviewed by Cursor Bugbot for commit 29877b3. Configure here.


Generated by Claude Code

Assisted-by: Claude Code:claude-opus-5-5
A requirements.txt line such as `wheels/six-1.16.0-py3-none-any.whl`,
`six-1.16.0-py3-none-any.whl` or `dist/six-1.16.0.tar.gz` is installed
by pip as a local, unpatched artifact. VEX discovery only treated a line
as a path when it began with `.`, `/` or another non-alphanumeric
character, so these spellings gave no evidence and `vex` attested
not_affected for a Socket wiring of the same release in Pipfile.lock.

Read a line as a path the way pip does: it holds a path separator,
starts with something other than a letter or digit, or names an
archive (`.whl`, `.tar.gz`, `.zip`, ...). `name@<location>` stays a
PEP 508 direct reference, as in pip.

Fixes #1587

Assisted-by: Claude Code:claude-opus-5-5
Move the "pip installs this as a local artifact" rule into
utils::requirements beside the shared requirements grammar, and follow
pip more closely:

- `six@https://...` (no spaces) is a PEP 508 reference to six, not a
  bare url, as pip reads it.
- A path's `[extras]` are cut before its filename is read, so
  `wheels/six-1.16.0-...whl[socks]` also contests the wiring.
- The archive test splits `.tar.<ext>` the way pip's splitext does.

Refs #1587

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review October 16, 2026 04:48
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Oct 16, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Labeled Ready for review at head 3a4de37.

  • CI: 36/36 checks green (50 skipped). No main-wide failures.
  • Bugbot: reviewed 3a4de37, no findings; no open review threads.
  • Reviewer focus: requirement_location in crates/socket-patch-core/src/utils/requirements.rs now treats bare (alphanumeric-leading) wheel paths as paths, the way pip does; the pipenv e2e covers it.

Generated by Claude Code

@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 20, 2026
Port of #1639. setup-uv installs the latest uv when no version is
given, and uv 0.13.2+ refuses the `environments = []` pylock that
Pipenv 2026.8.0 writes ("The target environment is not supported by
the lockfile"). That broke the e2e_vex_build pipenv leg on main and in
the merge queue, unrelated to this change. Pin uv 0.13.1, the last
version those legs passed on. This no-ops once #1639 lands.

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] Dequeued on e2e (ubuntu-latest, e2e_vex_build, pipenv:: --ignored, 2026.8.0): pipenv_pylock_projects_wire_what_pipenv_installs fails with uv pip install -r pylock.toml → "The target environment is not supported by the lockfile". It isn't this PR's failure. The same leg fails on main's nightly and in the queue for #1605 and #1614. setup-uv floats to the latest uv, and uv 0.13.2+ refuses Pipenv's environments = [] pylock. I reproduced it locally: uv 0.13.1 installs, uv 0.13.4 refuses.

I ported #1639's pin (uv 0.13.1 in ci.yml and pipenv-compatibility.yml) in 29877b3, after merging main. The pin no-ops once #1639 lands. The PR needs re-queuing once CI is green.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Wenxin Jiang (@Wenxin-Jiang) this changed after your approval (on 3a4de374), so it needs another look before it goes through the merge queue.

Besides merges from main, the only new commit is 29877b3: the CI-only uv pin from #1639, byte-for-byte the same 12 added lines (version: "0.13.1" on the two setup-uv steps in ci.yml and pipenv-compatibility.yml). No crate code changed. It's there because uv 0.13.2 fails the pipenv:: e2e leg on every merge-queue entry. Once #1639 lands it does nothing.

If that's fine with you, re-approving 29877b3d is all this needs.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

bugbot run


Generated by Claude Code

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 29877b3. Configure here.

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Ready for review re-confirmed at the new head (burn-down agent).

  • Head: 29877b3
  • CI: 55 (36 success, 19 skipped) green. No main-wide failures.
  • Bugbot: reviewed 29877b3, no findings; no unresolved review threads.
  • Mergeable: clean. The head changed after the earlier approval (main merges plus the setup-uv pin port), so it needs a fresh approval before re-queueing.
  • Slack: not announced this run (send tool unavailable); the next run will retry.

Generated by Claude Code

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

Labels

Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review

Projects

None yet

3 participants