Skip to content

osv-scan: derive scan targets from git ls-files, never the directory walk - #26

Merged
bdelanghe merged 1 commit into
mainfrom
claude/cleanup-pr-resolution-za2kjq
Aug 6, 2026
Merged

osv-scan: derive scan targets from git ls-files, never the directory walk#26
bdelanghe merged 1 commit into
mainfrom
claude/cleanup-pr-resolution-za2kjq

Conversation

@bdelanghe

@bdelanghe bdelanghe commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Closes bounded-systems/.github#103 — the class fixed in .github#102 for repo-standard.yml, ported to the reusable lane every deps.yml caller uses.

The defect

osv-scanner's -r walk applies .gitignore patterns without git's tracked-file exemption, so a repo that lists its own committed lockfile in .gitignore has it silently skipped, and --allow-no-lockfiles converts "extracted nothing" into exit 0. hooksmith#108 shipped sixteen advisories behind that green for months.

The fix

  • New Discover scan targets step — tracked lockfiles from git ls-files against the same basename list as repo-standard.yml (deno.lock deliberately absent there and here), plus the convert step's generated deno-lock.cdx.json SBOMs via find (untracked by construction, so they can't come from ls-files). Explicit --lockfile= args replace scan source -r --allow-no-lockfiles ..
  • "Scanned nothing" ≠ "scanned and clean" — zero targets is a logged ::notice:: explicit pass with the scan step skipped; an empty target list reaching the scan step anyway is a hard red. --allow-no-lockfiles is gone entirely.
  • Convert step's deno.lock discovery moves findgit ls-files, same authority principle.
  • Exit-code triage, report-only, and grace-expires behavior untouched (all 13 existing posture/grace tests pass unchanged).
  • New Discovery test suite in test_scan_posture.py runs the step's actual run: block against synthesized git repos — centered on the gitignored-but-tracked lockfile regression case. flake.nix lends the suite gitMinimal (same parity shape as env-record borrowing nodejs).

Verification — the Extract calls counter, as .github#103 asks

Synthesized hooksmith-shape repo (tracked package-lock.json carrying lodash 4.17.20, listed in .gitignore, plus the synthetic deno.lock fixture), scanned with the pinned v2.4.0 binary:

invocation Extract calls result
old: scan source -r --allow-no-lockfiles . 0No package sources found exit 0 (green, blind)
new: explicit targets from discovery 2 3 known vulnerabilities (1 High, 2 Medium) → exit 1 hard; exit 0 + ::warning:: under report-only

Against this repo itself (what self-test's scan job runs): fixture deno.lock converted → 1 scan target1 Extract calls → 0 vulnerabilities → exit 0.

Not in this PR

  • Caller pin bumps — merge triggers release-tag (paths include this workflow), which mints the next patch tag; Dependabot rewrites the fleet's SHA pins from there. No template bytes changed, so no caller drift is introduced.
  • Caller-repo before/after sweep — hooksmith, repo-health, and front-desk-scheduler aren't in this session's scope; .github#103 records the by-hand sweep that found no other hidden lockfile, and this change makes that sweep unnecessary going forward.

🤖 Generated with Claude Code

https://claude.ai/code/session_016JEQgLpoVWWs82ykpqMBL3

…walk

Port of .github#102's fix into the reusable lane, closing .github#103 —
the .gitignore blindness fixed in repo-standard.yml was still live here.

osv-scanner's -r walk applies .gitignore patterns without git's
tracked-file exemption, so a repo that gitignored its own committed
lockfile scanned nothing, and --allow-no-lockfiles turned that into a
green check (hooksmith#108: sixteen advisories behind a green hard-fail
lane for months; the tell is "0 Extract calls" next to exit 0).

- New "Discover scan targets" step: tracked lockfiles via git ls-files
  against repo-standard.yml's basename list (deno.lock deliberately
  absent, as there), plus the convert step's generated deno-lock.cdx.json
  SBOMs via find (untracked by construction). Explicit --lockfile= args
  replace `-r --allow-no-lockfiles .`; zero targets is a logged,
  explicit pass and the scan step is skipped, so "scanned nothing" and
  "scanned and clean" can never look alike.
- Convert step's deno.lock discovery moves find -> git ls-files for the
  same authority principle.
- Scan step refuses an empty target list (the if: gate should make that
  unreachable; if it isn't, red, not a scan of nothing). Exit-code
  triage, report-only grace, and grace-expires are untouched.
- test_scan_posture.py: Discovery suite over synthesized git repos —
  the gitignored-but-tracked lockfile regression case, git-authority in
  both directions, SBOM pickup, exact-basename matching — plus the
  empty-TARGETS guard case. flake.nix lends the posture suite gitMinimal
  (same parity shape as env-record's nodejs).

Verified end-to-end with the pinned v2.4.0 binary on a synthesized
hooksmith-shape repo (tracked package-lock.json with lodash 4.17.20,
gitignored): old invocation 0 Extract calls / exit 0; new invocation
2 Extract calls / 3 known vulnerabilities / exit 1 hard, exit 0 +
warning under report-only. Against this repo itself: fixture SBOM
converted and scanned, 1 Extract call, exit 0.

Closes bounded-systems/.github#103

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016JEQgLpoVWWs82ykpqMBL3
@bdelanghe
bdelanghe marked this pull request as ready for review August 6, 2026 14:53
@bdelanghe
bdelanghe merged commit 05dde82 into main Aug 6, 2026
10 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in Front Desk Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

ci-workflows osv-scan.yml still discovers via --recursive: the .gitignore blindness #102 fixed here is live in the other lane

2 participants