Skip to content

fix(supply-chain): re-sync Cargo.lock to unblock the vet gate, and trust ewf's publisher - #5

Merged
h4x0r merged 2 commits into
mainfrom
fix/lock-refresh-vet-and-csv
Aug 5, 2026
Merged

fix(supply-chain): re-sync Cargo.lock to unblock the vet gate, and trust ewf's publisher#5
h4x0r merged 2 commits into
mainfrom
fix/lock-refresh-vet-and-csv

Conversation

@h4x0r

@h4x0r h4x0r commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Two commits, both supply-chain hygiene. The second is unverifiable without the first, which is why they share a PR — but they are separate commits and read independently.

1. Cargo.lock re-sync — the vet gate has not been running at all

cargo vet shells out to cargo metadata --locked, and that has been failing outright:

ERROR   × `cargo metadata` exited with an error:
  │ error: cannot update the lock file ... because --locked was passed to prevent this

So the gate aborts before it evaluates a single crate. It has not been catching anything.

Root cause: PR #3 (ba519d9, scope OpenDAL backends to evidence-transfer targets). It cut 72 lines from Cargo.toml, dropping the cloud/object-store backends and their feature closure, and never regenerated Cargo.lock. The lock has carried the pre-#3 dependency graph ever since.

This is a re-resolution, not an update

No cargo update was run. Cargo keeps every pin the manifest can still reach and drops the ones it cannot. Measured on the (name, version) pair sets:

old 955 pairs
new 805 pairs
removed 150
added 0

The new lock is a strict subset of the old one — verified set-theoretically, not by reading the diff.

Nothing moved forward. The 16 packages that appear to have "changed" each lost a duplicate older major once its only consumer left the graph:

rand 0.7.3 · http 0.2.12 · hyper 0.14.32 · tower 0.4.13 · prost 0.12.6 and 0.13.5 · memmap2 0.5.10 · wasi 0.9.0 · rand_core 0.5.1 · sync_wrapper 0.1.2 · http-body 0.4.6 · tokio-rustls 0.24.1 · memoffset 0.7.1

One inversion worth naming explicitly: windows 0.62.2 was dropped and 0.52.0 retained — again because the 0.62 consumer left, not because anything downgraded.

Whole trees gone with their roots: axum, compio, cacache, bson, etcd-client, hickory-resolver, librocksdb-sys, bindgen.

Because nothing is added and nothing advances, this cannot introduce a new major, cannot raise the MSRV, and cannot bring in a licence cargo deny has not already seen.

The 7 +name = lines in the diff are relocations, not additions — packages re-emitted at a new offset after their neighbours were deleted.

2. ewf — trust the publisher instead of claiming we authored it

supply-chain/config.toml carried:

[policy.ewf]
audit-as-crates-io = false

That is ADR-0018 case 1, which means "ours and a workspace member". ewf is ours but it is not a member here — blazehash pulls it from crates.io like any other dependency. The policy told cargo-vet to skip auditing it on the strength of a claim that was not true.

The fleet's common defect is the opposite one: repos exempt their own crates and understate their posture. This entry overstated it, which is the direction that costs something — a compromised or substituted ewf release would have walked through the gate unexamined.

Verified against the registry before trusting. ewf has exactly one owner and every published version is theirs:

owners:  h4x0r | Albert Hui | user
0.4.7 -> published_by: h4x0r
0.4.6 -> published_by: h4x0r
...

So this is ADR-0018 case 2:

$ cargo vet trust ewf h4x0r --criteria safe-to-deploy

yielding a claim that is actually true — we trust this publisher, bounded to their user-id and a dated window:

[[trusted.ewf]]
criteria = "safe-to-deploy"
user-id = 347968 # Albert Hui (h4x0r)
start = "2026-03-05"
end = "2027-08-02"

It does not assert a human read the source. That is what a certify record would claim, and what audit-as-crates-io = false implied.

cargo-vet removed the now-redundant [[exemptions.ewf]] 0.2.3 itself — case 2 outranks case 4, and keeping both would leave the weaker mechanism carrying a load it no longer bears.

The imports.lock churn is fallout from commit 1: cexpr's publisher record drops out because bindgen left the graph, and one upstream mozilla entry lost an inline comment on re-fetch.

Verification

No honest RED commit exists for either change — the failure is a tooling abort, not a behaviour a test can assert. Before/after output stands in its place:

BEFORE  ERROR × `cargo metadata` exited with an error:
        error: cannot update the lock file ... because --locked was passed

AFTER   Vetting Succeeded (170 fully audited, 5 partially audited, 628 exempted)
gate result
cargo build pass
cargo test pass — 214 passed, 0 failed, 10 ignored
cargo clippy --all-targets -- -D warnings pass
cargo fmt --check pass
cargo vet pass (was aborting)
cargo deny check FAIL — pre-existing, see below

Known red this PR does not fix

cargo deny check fails, and fails identically on pristine origin/main — reproduced on a detached worktree at 366a799:

error[vulnerability]: Stores can mix up type indices between engines
    wasmtime 25.0.3 — RUSTSEC-2026-0222
    Solution: >=24.0.12,<25.0.0 OR >=36.0.13,<37.0.0 OR >=46.0.2,<47.0.0 OR >=47.0.3
    wasmtime v25.0.3 <- yara-x v0.9.0 <- blazehash v0.2.6
warning[yanked]: spin 0.9.8
advisories FAILED, bans ok, licenses ok, sources ok

The lock re-sync cannot have introduced it — the new graph is a strict subset of the old. Closing it means moving off yara-x 0.9.0, which pins wasmtime 25.x. That is a dependency decision, not a drive-by, so it is flagged rather than attempted here.

Follow-ups deliberately not bundled

  • 157 orphaned vet exemptions. The prune leaves cargo vet warning about unnecessary exemptions: 786 entries before, 629 after cargo vet prune. It is a WARN, cargo vet --locked still exits 0, nothing blocks. Left out to keep this diff readable.
  • ewf is caret-trapped. Cargo.toml:112 pins ewf = { version = "0.2", optional = true }; the lock sits at 0.2.3 while the registry is at 0.4.7 (2026-07-25) — a layer-1 freshness trap cargo update cannot cross. Widening it adds packages and would destroy the "strict subset, nothing added" property that makes commit 1 safe to review at a glance. It wants its own PR, plus a check that 0.2 -> 0.4 is API-compatible.
  • ImageFormat::detect dispatches on file extension (src/forensic_image/mod.rs:19-37) where the fleet standard is content-sniffing. That is an ADR-0011 architectural call, reported not attempted.

🤖 Generated with Claude Code

h4x0r and others added 2 commits August 5, 2026 15:40
`ewf = { version = "0.2", optional = true }` cannot reach 0.4.x. `cargo update`
will not cross a caret, so the pin has sat at 0.2.3 while the crate moved to
0.4.7 (published 2026-07-25) — the layer-1 freshness trap, invisible to both
`cargo update` and Renovate's default rangeStrategy.

`ewf` is not a spare wheel here. `forensic-image` is a DEFAULT feature and it
gates `dep:ewf`, so every stock build ships this code path:

    src/forensic_image/ewf_backend.rs:2   use ewf::EwfReader;
    src/forensic_image/mod.rs:261         ImageFormat::Ewf => ewf_backend::verify_ewf(path)

0.2 -> 0.4 crosses two 0.x minors, which are breaking by convention, so this was
checked rather than assumed. The surface actually consumed is `EwfReader::open`,
`total_size`, `stored_hashes`, `metadata`, and `verify` plus the fields of what
those return. All of it still compiles, and — the part that matters — still
produces the same answers on a real image:

    test tests::verify_ewf_image_passes ... ok
    test tests::verify_ewf_image_returns_stored_hashes ... ok
    test tests::verify_ewf_image_returns_metadata ... ok
    test tests::detect_ewf_format ... ok
    test tests::cli_verify_image_e01 ... ok
    test result: ok. 19 passed; 0 failed; 0 ignored

Those are not compile-only. `tests/data/nps-2010-emails.E01` is a real 518,680-byte
EWF image from the NPS corpus; the test decompresses it, computes MD5 and SHA-1
over the media, and compares against the hashes the original 2010 acquisition
tool stored inside the file. The expected values were authored by a third party,
not by us, so a silent behavioural regression in 0.4's reader or verifier would
surface as a mismatch rather than a passing tautology.

The dependency graph gets smaller, not larger. One in, five out:

    ADDED  : ewf 0.4.7
    REMOVED: ewf 0.2.3, instant 0.1.13, parking_lot 0.11.2,
             parking_lot_core 0.8.6, redox_syscall 0.2.16, socket2 0.5.10

Worth correcting one thing about the unpushed commit 41e1090, which does the same
widening and was used only as a starting point to verify: its lock diff shows
`adler2` being ADDED to ewf's dependencies. That is not true against a re-synced
lock — `adler2` is already present from the earlier adler->adler2 migration, so
the real delta is a net removal of five packages.

`[[trusted.ewf]]` already covers 0.4.7: the trust is bound to the publisher and a
date window, not to a version, and 0.4.7 was published inside it. cargo-vet
refreshed the `imports.lock` publisher record from 0.2.3 to 0.4.7 by itself.

    Vetting Succeeded (169 fully audited, 5 partially audited, 624 exempted)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Re-syncing Cargo.lock dropped 150 package-versions from the graph. Their
cargo-vet exemptions stayed behind, so `cargo vet` has been warning:

    WARN Your supply-chain has unnecessary exemptions which could be relaxed or pruned.
    WARN   Consider running `cargo vet prune` to prune unnecessary exemptions and imports.

    $ cargo vet prune

Pure deletion — 713 lines out, none in:

    supply-chain/config.toml  | 628 ------------------------------------
    supply-chain/imports.lock |  85 ------

Verified rather than assumed. Comparing exemption `(name, version)` pairs against
the package-versions actually in the lock:

    exemption entries: 786 -> 629   removed=157  added=0
    removed exemptions whose exact (name, version) is still in the lock: 0

So every pruned entry names a package-version that genuinely left the graph. The
name-level view is misleading here and worth stating: 20 of the removed names —
`rand`, `http`, `hyper`, `tower`, `prost`, `windows` and friends — still appear
in the lock. Those are the duplicate-major cases. The exemption removed is for
the OLD version that left; the surviving version keeps its own entry.

All four aggregate import sets are intact, as ADR-0018 requires:

    [imports.bytecode-alliance]  [imports.embark]  [imports.google]  [imports.mozilla]

One inert leftover cargo-vet chose not to prune: `crossbeam-epoch 0.9.18` while
the lock carries 0.9.20. An exemption for an absent version grants nothing, and
removing it is cargo-vet's call to make, not a hand edit.

    Before:  Vetting Succeeded (170 fully audited, 5 partially, 628 exempted) + 2 WARN
    After:   Vetting Succeeded (170 fully audited, 5 partially, 628 exempted)

Kept out of the lock PR deliberately. That PR's whole value is that a reviewer
can confirm "strict subset, nothing added" at a glance, and folding 628 deleted
policy lines into it would destroy exactly that property.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@h4x0r
h4x0r force-pushed the fix/lock-refresh-vet-and-csv branch from 8bd2dde to 2077fe0 Compare August 5, 2026 22:40
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedewf@​0.2.3 ⏵ 0.4.796 -110093100100

View full report

@h4x0r
h4x0r marked this pull request as ready for review August 5, 2026 23:14
@h4x0r
h4x0r merged commit f9d13a7 into main Aug 5, 2026
8 of 9 checks passed
@h4x0r
h4x0r deleted the fix/lock-refresh-vet-and-csv branch August 9, 2026 15:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant