- Add --existing-db flag to enrich command to skip already-enriched advisories
- Add --timeout-secs flag to stop processing after a time budget
- Create .github/workflows/enrich.yml that runs hourly on a 55-minute budget
- Workflow commits enriched vuln_db.json to repo, checkpointing progress
- Each run picks up where the last left off, progressively enriching the backlog
https://claude.ai/code/session_01Pp3k3jGUtnTTqvMMr1uP4Y
Scanner fixes:
- Block comment tracking: skip lines inside /* ... */ blocks
- Skip `use` statements from being matched as call sites
- Free function call detection: `parse_cookie(...)` after direct import
- Type-aware suppression: when the receiver's type is positively known
and doesn't match the vulnerable type, suppress the finding entirely
(e.g., .abort() on MyHandle vs JoinHandle)
Golden test improvements:
- All assertions are now specific: exact counts (deps, reachable symbols,
files scanned), exact advisory IDs listed vs reachable, exact call site
locations (file:line), exact confidence levels (HIGH vs MEDIUM)
- Each test documents its fixture layout and expected positive/negative
findings in a header comment
New edge_cases_project fixture covering:
- Aliased imports (Decoder as HyperDecoder → dec.decode detected)
- Free function calls (parse_cookie after direct import)
- Commented-out code (block & line comments correctly skipped)
- False positive suppression (abort() on MyHandle, parse() on String)
- Typed method calls (jar.add(c) with explicit CookieJar type)
38 tests total (33 unit + 5 integration), all passing.
https://claude.ai/code/session_011sdj18ZvQYbDVwEKqrWDj1
Type tracking (type_tracker.rs):
- Uses syn AST parsing to resolve variable types from function parameters,
let bindings with annotations, constructor calls (Type::new()), struct
literals, builder patterns, and closure parameters
- Integrated into scanner to promote method-call matches from Medium to
High confidence when the receiver's type is known
Golden integration tests:
- vulnerable_project: 4 vulnerable deps, 3 with reachable calls across
multiple files (qualified calls, typed method calls, constructor-inferred
types). Verifies regex dep is listed but Compiler::compile is NOT reachable.
- safe_project: patched deps (hyper, smallvec) excluded, vulnerable deps
(tokio, regex) listed but no symbols reachable. Reports POSSIBLY SAFE.
- clean_project: no vulnerable deps at all. Reports CLEAN.
37 tests total (33 unit + 4 integration), all passing.
https://claude.ai/code/session_011sdj18ZvQYbDVwEKqrWDj1
Implements the next phase of cargo-deep-audit: given a Rust project and the
enriched vulnerability database, determine which vulnerable symbols are
actually called from user code.
New modules:
- lockfile.rs: Parse Cargo.lock to extract dependency names and versions
- scanner.rs: Scan .rs source files for references to vulnerable symbols
using import tracking (use statements) and call pattern matching, with
High/Medium confidence levels
- analyzer.rs: Orchestrate the full pipeline — load vuln_db, match against
lockfile versions (semver-aware), scan source, produce structured report
Changes:
- main.rs refactored into subcommands: `enrich` (Phase 1) and `analyze` (Phase 2)
- db.rs/diff_analyzer.rs: Added Deserialize support to load vuln_db.json
- CI workflow updated for subcommand syntax
- 24 tests total (21 unit + 3 integration), all passing
https://claude.ai/code/session_011sdj18ZvQYbDVwEKqrWDj1
1. Impl body changes with no fn context: When the fn declaration is too
far above for git to include in hunk headers or context lines, body
changes were silently dropped. Now emits symbols at the impl-type
level with a <method> placeholder (e.g. KeccakXofState::<method>).
2. PR diff uses files endpoint: Previously resolved PRs to their merge
commit, which could be a version-only bump with no .rs files (e.g.
quinn-proto PR #2559). Now uses /pulls/{n}/files to get all changes
across the entire PR.
3. Nested generics in impl regex: The impl block regex used [^>]* which
broke on nested generics like impl<T: Foo<Bar>>. Now uses .* for
greedy matching to the last >.
https://claude.ai/code/session_01AeNG3herWfKhos9uZVUY5d
When a multi-hunk diff has consecutive hunks in the same function,
git may show the impl block (not the fn) in the second hunk header.
Previously this reset current_context_fn to None, causing body-only
changes to be silently dropped.
Now hunk headers with impl but no fn preserve the existing fn context.
This fixes cases like libcrux-sha3's squeeze() where the actual
vulnerability fix (loop index change) was missed because the second
hunk header showed `impl KeccakXofState` instead of `fn squeeze`.
https://claude.ai/code/session_01AeNG3herWfKhos9uZVUY5d
- Parse markdown heading as title fallback when TOML title is missing,
fixing the "(no title)" entries
- Filter out test files (tests/, *_test.rs) from vulnerable symbols
since test code isn't callable library API
- Fix module path generation to handle workspace layouts
(crates/foo/src/bar.rs → foo::bar) and strip src/ properly
- Replace hyphens with underscores in module paths to match Rust
crate naming conventions (pyo3-ffi → pyo3_ffi)
https://claude.ai/code/session_01AeNG3herWfKhos9uZVUY5d
The RustSec advisory-db uses .md files with TOML in a fenced code block,
not plain .toml files. The parser now extracts the TOML block from markdown.
Also fixes:
- --limit now means "collect up to N enriched entries" instead of
"take first N candidates", so it keeps scanning until enough are found
- Suppressed dead_code warnings on Issue variant and deserialization-only fields
- Updated test fixtures to match the .md format
https://claude.ai/code/session_01AeNG3herWfKhos9uZVUY5d
Two jobs:
- test: builds and runs cargo test
- enrichment-dry-run: runs the pipeline against 10 real advisories
using the Actions GITHUB_TOKEN, uploads vuln_db.json as artifact
https://claude.ai/code/session_01AeNG3herWfKhos9uZVUY5d