release: v0.9.8 — code-review-driven hardening (fuzz, coverage, lint, lib split)#27
Merged
release: v0.9.8 — code-review-driven hardening (fuzz, coverage, lint, lib split)#27
Conversation
Adds an informational coverage job to .github/workflows/ci.yml: - runs cargo-llvm-cov on Ubuntu after the test matrix - uploads lcov.info as a 30-day retention artifact - posts a sticky PR comment (marocchino/sticky-pull-request-comment) with overall line coverage % (computed from lcov DA: records) Intentionally NOT added to required-status-checks and NOT gated with --fail-under-lines. The plan is to let coverage be visible for 2-3 releases before introducing a ratchet (v0.9.9 candidate). Workflow gains pull-requests:write so the sticky-comment action can upsert. CONTRIBUTING.md gains a short Coverage section under Tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a standalone fuzz/ sub-workspace with three libfuzzer targets,
one per SBOM parser:
fuzz/fuzz_targets/parse_cyclonedx.rs
fuzz/fuzz_targets/parse_spdx.rs
fuzz/fuzz_targets/parse_syft.rs
Each target uses a two-stage decode (serde_json::Value -> bomdrift
parser) so the fuzzer's budget is spent on bomdrift-side parsing
rather than re-fuzzing serde_json's well-tested layer.
Seed corpus is bootstrapped from tests/fixtures/{cdx,spdx,syft}*.json
under fuzz/corpus/<target>/. cargo-fuzz will grow these from there.
The new .github/workflows/fuzz.yml runs on PRs that touch
src/parse/** or fuzz/** (60s budget per target) and on a Sunday
schedule (600s budget). Crash artifacts are uploaded on failure.
Nightly toolchain is required by libfuzzer instrumentation; the
fuzz/ directory is its own [workspace] root so the main crate's
stable pin is unaffected.
README gains a 'Continuous fuzzing' subsection under Release signing.
This job is informational and is NOT in the required-status-checks
list.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Annotate all 16 unsafe blocks that lacked SAFETY comments and turn on
clippy::undocumented_unsafe_blocks crate-wide so future sites are caught
at lint time. All annotated sites are env::{set_var,remove_var} calls
serialized by clock::test_env_lock() or an equivalent process-wide
mutex held by the test.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Tighten the lint policy crate-wide so accidental panics in production
code are caught at lint time:
Test modules opt out via an inner allow attribute; tests legitimately
use unwrap/expect for terse assertions on known-good fixtures.
Audited the 4 production .expect() sites surfaced by the new lints --
all are true invariants, kept as .expect("invariant: ...") with a
narrowly-scoped #[allow] carrying a reason rationale:
- baseline.rs: as_object_mut() after is_object() check
- render/json.rs: to_string_pretty on owned Value with string keys
- render/sarif.rs: same
- vex.rs: same
No production .unwrap() sites were flagged.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
src/lib.rs went from 1341 lines (47 KB) to 31 lines: it now only declares the public module tree and re-exports the orchestration entry points. All other code -- run_diff and its private helpers, the public predicates (tripped, any_kev, any_epss_at_or_above, budget_tripped), the public entry point run(), the embedded INIT_* config templates, the lib tests -- moved verbatim into the new src/run.rs. Behavior-preserving: every consumer keeps its historical paths (bomdrift::run, bomdrift::tripped, ...) via re-exports in lib.rs. Test count unchanged (432 tests, all green); fmt + clippy 1.88 strict + cargo test --release --all-features all pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Bump Cargo.toml + Cargo.lock 0.9.7 → 0.9.8. - CHANGELOG.md: v0.9.8 entry covering the five hardening items (parser fuzzing via cargo-fuzz, CI coverage report via cargo-llvm- cov, unwrap/expect lint policy, undocumented-unsafe-blocks lint with 16 SAFETY comments added, lib.rs orchestration extracted into src/run.rs). Includes scope notes for the four explicitly-deferred v1.0 candidates. - README.md, docs/src/quickstart.md, .github/ISSUE_TEMPLATE/action- broke.md: bump example version pins from v0.9.7 → v0.9.8. 432 tests, fmt + clippy 1.88 strict clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SBOM diff
Added (2)Show details
Version changed (1)Show details
False positive? Report it · Suppress a finding? Comment |
Coverage reportLine coverage: 85.7% (9153 / 10679 lines) Full lcov report available as workflow artifact v0.9.8 introduces this report; |
The three fuzz targets used unqualified `<Parser>::parse(value)` which
fails with E0599 because `parse` is a trait method defined on
`SbomParser`, not an inherent method. Add `use bomdrift::parse::
{SbomParser, <module>::<Parser>}` to each target.
Caught by all three fuzz CI jobs failing on PR #27 first run.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v0.9.8 — code-review-driven hardening
External agent reviewed bomdrift against the v0.9.7 state, surfacing
nine recommendations (P1/P2/P3). v0.9.8 takes five of the six high-
leverage items; the other four (mutation testing, remaining file
splits, calibration FPR docs, coverage gate ratchet) are explicitly
deferred to v1.0+ with documented rationale.
Highlights
with three `cargo-fuzz` libfuzzer targets (CycloneDX / SPDX / Syft).
Runs 60s per target on PRs that touch `src/parse/**`, and 600s
weekly on cron. Closes the textbook "untrusted-input parser" gap
for a security tool.
posts a sticky PR comment with line-coverage %, emits `lcov.info`
as a workflow artifact. Informational for now —
`--fail-under-lines` deferred until baseline visible across 2-3
releases.
enforced. Production audit found 4 sites; all true invariants,
kept as `expect()` with explicit `#[allow(reason = ...)]`
rationale. Test modules opt-out via inner allow. Zero production
`.unwrap()` remain.
needed annotation). Enforced via
`#![warn(clippy::undocumented_unsafe_blocks)]`.
orchestration into a new `src/run.rs`. Public API surface
byte-preserved via re-export. Behavior-preserving — all 432 tests
pass without modification beyond import-path updates.
What's deferred to v1.0+
Process
Two parallel background sub-agents on isolated git worktrees
(established v0.9.5 pattern, fifth release in a row):
comments → Phase 2 unwrap-lint sweep + audit → Phase 3 lib.rs split
into run.rs.
with rust): coverage job → fuzz/ sub-workspace + workflow.
Both branches merged cleanly into `release/v0.9.8` with zero
conflicts (disjoint file ownership).
Test status
clean (Rust 1.88 toolchain).
Deps
No new top-level deps. `cargo-fuzz` and `cargo-llvm-cov` are
CI-installed tools; `fuzz/Cargo.toml` is a separate sub-workspace
with its own `libfuzzer-sys` dep that doesn't affect the main
crate.
Post-merge checklist (maintainer)
`feat/v0.9.8-platform` branches.
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com