Skip to content

fix(deps): widen ewf 0.2 -> 0.4, caret-trapped below the maintained line - #8

Draft
h4x0r wants to merge 1 commit into
fix/lock-refresh-vet-and-csvfrom
fix/widen-ewf-caret-0.4
Draft

fix(deps): widen ewf 0.2 -> 0.4, caret-trapped below the maintained line#8
h4x0r wants to merge 1 commit into
fix/lock-refresh-vet-and-csvfrom
fix/widen-ewf-caret-0.4

Conversation

@h4x0r

@h4x0r h4x0r commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Stacked on #5. Base is fix/lock-refresh-vet-and-csv, because cargo vet cannot run until that PR's lock re-sync lands. Retarget to main once #5 merges.

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). This is the layer-1 freshness trap — invisible to cargo update and to Renovate's default rangeStrategy.

This is a live code path, not a spare wheel

forensic-image is a default feature and it gates dep:ewf, so every stock build ships this:

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 — checked, not assumed

0.x minors are breaking by convention, so a version bump alone would not be evidence of anything. The surface actually consumed is EwfReader::open, total_size(), stored_hashes(), metadata(), verify(), plus the fields of what those return.

All of it compiles. More importantly, it still produces the same answers on a real image:

test tests::detect_ewf_format ... ok
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::cli_verify_image_e01 ... ok

test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

These are not compile-only, and they are not skipped. I checked specifically, because a fixture-gated suite that silently skips would have made "it compiles" the entire strength of the claim.

tests/data/nps-2010-emails.E01 is present — 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 wrote inside the file. The expected values were authored by a third party years before this code existed, so a silent behavioural regression in 0.4's reader or verifier surfaces as a mismatch rather than as a passing tautology.

The graph gets smaller

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

instant and parking_lot 0.11 are both long superseded, so this drops old surface rather than adding new.

One correction to the unpushed commit 41e1090

That commit does the same widening and was used only as a starting point to verify, not as a change to trust. 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. The real delta is a net removal of five packages, not an addition.

Supply chain

[[trusted.ewf]] from #5 already covers 0.4.7: the trust binds 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 on its own.

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

Gates

gate result
cargo build pass
cargo test pass — 0 failed, incl. 19 real-E01 tests
cargo clippy --all-targets -- -D warnings pass
cargo fmt --check pass
cargo vet pass
cargo deny check fails on RUSTSEC-2026-0222 (wasmtime 25.0.3 via yara-x 0.9.0) — pre-existing on main, unrelated, detailed in #5

Note the exemption count drifts 628 -> 624 as four more entries go inert with instant and the parking_lot pair leaving. #7 prunes orphaned exemptions; if it lands after this, it will sweep those too.

🤖 Generated with Claude Code

`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>
@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 commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

CI does not run on this PR, and that is not the same as CI passing.

.github/workflows/ci.yml triggers on pull_request: branches: [main] only. This PR targets fix/lock-refresh-vet-and-csv, so the CI workflow is never dispatched — the only green checks visible here are Socket Security, which runs on every PR. Read the empty check list as "not run", not "clean".

The gates were run locally instead, on this exact branch:

gate result
cargo build pass
cargo test pass, 0 failed
cargo clippy --all-targets -- -D warnings pass
cargo fmt --check pass
cargo vet pass
cargo deny check fails on RUSTSEC-2026-0222 — pre-existing on main, see #5

Retargeting this PR to main once #5 merges will dispatch the real CI run. Please do not merge on the strength of the check list as it currently reads.

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