Skip to content

Cargo apply on a cold or pruned registry cache now exits 0 as "lockfile-only", then the next cargo build downloads and compiles the unpatched crate (regression from #555) #616

Description

[agent] Found by the scheduled Cargo bug-hunt routine (ledger #315).

Summary

#555 (the #403 fix) made apply treat a manifest purl that the project lock resolves but that isn't on disk as a calm package_not_installed "lockfile-only" skip that never fails the run. For npm that case means the package was deliberately not installed (a platform-gated optional dependency, --omit=dev). For Cargo it usually means the crate just hasn't been downloaded yet: a fresh CI runner or clone with an empty $CARGO_HOME, or a cache whose unpacked registry/src was pruned (cargo's GC or a manual rm -rf ~/.cargo/registry/src). The next cargo build downloads or re-extracts the crate unpatched.

In 4.0.0 this case exited 1 with "no matching packages were found on disk. Check that packages are installed". On main it exits 0 with status: "success", and --silent prints nothing. A CI step like socket-patch apply && cargo build --locked now goes green and ships the unpatched crate.

Impact

  • The patch is silently not applied in any pipeline that runs apply before cargo has fetched the crate.
  • The exit code and JSON status are the only signals a hook or CI step checks, and both report success.
  • VEX correctly omits the patch (not_applied), so the only visible symptom is a missing attestation.

Repro (Linux, cargo 1.93.1 and stable 1.97.0, main 045d7ec)

# The project depends on cfg-if = "=1.0.0" and has a Cargo.lock.
# .socket/manifest.json holds one pkg:cargo/[email protected] patch, with its blobs in .socket/blobs.
# The patch appends `pub fn socket_patched(){}` to src/lib.rs, and main.rs calls it (compile oracle).
export CARGO_HOME=$(mktemp -d)          # cold cache, as on a fresh CI runner
socket-patch apply --offline; echo $?   # main: 0  (4.0.0: 1)
cargo build --locked                    # error[E0425]: cannot find function `socket_patched`

Main prints:

Note: 1 manifest patch targets a package not installed on this host (resolved by the project lockfile; skipped):
  - pkg:cargo/[email protected]
Summary: 0 of 1 targeted patch applied, 0 already patched, 1 not found on disk
exit=0

The --json output has "status": "success" and a single skipped / package_not_installed event.

Pruned-cache variant: copy a warm $CARGO_HOME, delete registry/src but keep registry/cache/*/cfg-if-1.0.0.crate. Then apply --offline exits 0 the same way, and cargo build --locked --offline re-extracts the unpatched source from the .crate and fails the oracle.

Expected vs actual

  • Expected: CLI_CONTRACT (package_not_installed row) gives the reason for the calm skip: the lock resolves a package that the PM deliberately left uninstalled on this host ("a platform-gated optional dependency, a devDependency under --omit=dev"). A Cargo crate that the host build needs and that simply isn't fetched yet isn't that case. docs/ecosystems.md (Cargo: shared registry cache) says agent mode patches the crate "wherever the crawler finds it", so if it isn't found, nothing is patched, and the run should fail or at least warn and tell the user to run cargo fetch first, as 4.0.0 did.
  • Actual: exit 0 and status: success, then an unpatched build.

A cfg-gated crate that cargo won't download for the host target (for example a cfg(windows) dependency on Linux) is the cargo equivalent of the npm case. It should probably stay calm, so the fix may need to tell "not needed for this target" apart from "not fetched yet".

Matrix

OS cargo Cold CARGO_HOME Pruned registry/src
Linux 1.93.1 repro (exit 0, unpatched build) repro
Linux 1.97.0 stable repro not run (same CLI path)
Linux 4.0.0 release, same fixture exit 1, loud (good) n/a
macOS / Windows any untested (the CLI path is OS-independent) untested

The warm-cache control on main applies the patch and the build passes.

First bad

3a4883c, "Fix apply failing when patched deps are skipped (#403) (#555)". Release 4.0.0 behaves correctly.

Suspect code

  • crates/socket-patch-cli/src/commands/apply.rs:2300 (lockfile_resolved) counts every Cargo.lock entry as deliberately not installed.
  • crates/socket-patch-cli/src/commands/apply.rs:2250 and :1859 then drop those purls from the exit-code decision.

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