Skip to content

Cargo VEX: an ignored [patch] Socket pin still attests a transitive crate; bypass remedies name ambiguous or incomplete commands #2045

Open

Description

Follow-ups found while reviewing #2012 (the folded Cargo VEX stack). All three predate #2012 or are remedy text. None of them blocks it.

1. False attestation: an ignored [patch] Socket pin as a transitive crate's only wiring (also on main)

hosted_from_lock (vex/discover/cargo.rs) keeps the Cargo.lock ref whenever any declaration names the lock's socket-patch-<uuid> registry: regs.iter().any(|d| d.registry == reg). It doesn't check d.live. Cargo can ignore a root [patch.crates-io] serde = { registry = "socket-patch-<U>" } entry in two ways:

  • a [patch."https://github.com/rust-lang/crates.io-index"] table replaces [patch.crates-io];
  • a project-config [patch] item redefines the key.

If that ignored entry is the only wiring of a transitive crate, the ref is still attested. Cargo actually re-resolves serde from crates.io.

Reproduced on #2012's head (f1eb764), with a root manifest carrying that [patch.crates-io] pin and a crates.io-URL [patch] table, and a Socket-sourced serde 1.0.1 in the lock:

  • refs: [(pkg:cargo/serde@1.0.1, U, Hosted)]
  • unattested: []
  • diagnostics: [patched_ref_invalid] ("cargo ignores that [patch] entry")

The discovery diagnoses the entry as ignored and still attests the ref.

main has the same gate (regs.iter().any(|r| r.as_deref() == Some(reg))) and no [patch] precedence model at all, so it attests this shape too. #2012 didn't introduce it. The fix probably belongs in hosted_from_lock: count only live declarations for the "names this patch's registry" gate, and treat a ref whose only wiring is a dead [patch] pin like a reverted pin (patched_ref_invalid, no ref).

2. Remedy text: ambiguous cargo update -p / cargo tree -i beside the tagged vendored copy

When vex_cargo_patch_bypassed fires on a same-version lock entry, the detail suggests cargo update -p <crate> and cargo tree -i <crate>@<version>. The lock also holds the vendored copy at <version>+socket.<uuid>, and cargo ignores build metadata when matching a package spec. So both commands fail with "specification … is ambiguous". The remedy should print a source-qualified spec, for example registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4, or the git/registry source of the offending entry.

3. Remedy text: a stale entry from another registry gets no re-lock advice

The stale-entry check maps a lock source to a DeclSource only for crates.io and git (DeclSource::of_lock_source). Take a copy wired under [patch."https://my-corp.example/index"] (or [patch.my-corp]) with a stale registry+https://my-corp.example/index entry at the patched version. It isn't recognized as stale, so the user is sent to cargo tree -i to look for a declaring dependency that may not exist. Mapping registry+ / sparse+ sources to DeclSource::RegistryIndex(url) would reuse patched_by.

Checked and not an issue: sparse index URLs. #2012 compares sparse+ URLs with one trailing / ignored, and so does cargo. CanonicalUrl::new (src/util/canonical_url.rs) strips a trailing slash for every URL, and skips only the GitHub lower-casing and .git stripping for schemes containing +.

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

    bugSomething isn't workingpm:cargoCargo

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions