Skip to content

ci(security): scan bun.lock with osv-scanner and report to code scanning - #628

Merged
gascity-infra-agent[bot] merged 2 commits into
mainfrom
ci/osv-scan-bun-lock
Nov 5, 2026
Merged

gascity-infra-agent[bot] merged 2 commits into
mainfrom
ci/osv-scan-bun-lock

Conversation

@gascity-infra-agent

@gascity-infra-agent gascity-infra-agent Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

GitHub's dependency graph does not resolve bun.lock. The repository SBOM lists 36 packages, while bun.lock pins 206, so Dependabot alerts cannot see most of this repo's dependencies. Dependabot's bun ecosystem does version updates only, not security updates.

This PR adds .github/workflows/osv-scanner.yml. It runs on pushes to main, on pull requests, weekly (Monday 05:17 UTC) and on manual dispatch.

  • Scanner. It runs osv-scanner v2.7.0, installed from the release binary and checked against its SHA-256. osv-scanner reads bun.lock natively and finds all 206 packages. The step fails if bun.lock ever drops out of the scan.
  • Code scanning. It uploads SARIF under category osv-scanner, so OSV findings become code-scanning alerts. That is the coverage the dependency graph should have given. The upload is skipped on fork PRs.
  • Gate. scripts/osv-gate.ts fails the job on a HIGH or CRITICAL finding that osv-scanner.toml does not accept. HIGH or CRITICAL means CVSS >= 7.0, or, for an unscored advisory, a HIGH or CRITICAL label.
  • Waivers. Every waiver must have an ignoreUntil date and a reason. A waiver accepts a finding through any id or alias. Once its date passes it accepts nothing, so the scan does not flap on accepted risks and turns red again when a waiver lapses. osv-scanner.toml starts empty, because no risk is accepted today.
  • bun audit. The step in ci.yml stays. It checks the npm advisory feed on each PR; this workflow adds the OSV database, the scheduled re-check and the alerts.

Review fixes (max-effort review, 2026-11-05, commit 546cdbf)

  • Known-malicious packages now block. OSV MAL-* records (the OpenSSF malicious-packages feed) carry no CVSS score and no severity label, so the gate classed a known-malicious package as UNSCORED and let it pass. A finding with a MAL-* id or alias is now rated MALICIOUS and blocks; a waiver can still accept a false positive. This was checked against a real osv-scanner 2.7.0 report (flatmap-stream 0.1.1, MAL-2025-20690): before the fix that row was listed below the gate, after it the row blocks.
  • No dependency install scripts run under the scan job's token. The job holds security-events: write and passes its token to bun install as NODE_AUTH_TOKEN. The gate needs only smol-toml, so the install now runs with --ignore-scripts, and the workflow test pins that flag.
  • Tests. osv-gate.test.ts now has 20 tests. A mutation pass removed the 7.0 threshold, the expiry comparison, alias matching, the label fallback, the input checks, the exit codes, the MAL-* rule and --ignore-scripts; the tests caught all 14 mutants. The PR's CI is green on 546cdbf, and the install log shows bun install --frozen-lockfile --ignore-scripts followed by the gate's No unaccepted HIGH/CRITICAL finding.

CVEs

This PR fixes no CVE. It closes a coverage gap from round 4. The 2026-11-04 cve.now cross-check found registry clean (its two hits were false matches), but noted that Dependabot is blind to bun.lock.

Verification

  • Local scan. osv-scanner v2.7.0 with this workflow's flags on this tree reported Scanned bun.lock file and found 206 packages, with no vulnerabilities. The gate exited 0. The scan step was also run verbatim in a scratch copy.
  • Tests. bun test scripts/osv-gate.test.ts scripts/supply-chain-pins.test.ts passes: 40 tests.
    • osv-gate.test.ts covers the gate rules: the 7.0 threshold, the label fallback, matching by alias, and a waiver that still accepts on its expiry day but not the day after.
    • It also covers the allowlist format (a missing expiry or reason is rejected), the CLI exit codes 0, 1 and 2, and the workflow's triggers, job-scoped permissions, scanner pin and gate wiring.
    • supply-chain-pins.test.ts covers the new workflow's SHA pins and confirms there is no top-level write.
    • ci.yml now also asserts scripts/osv-gate.test.ts exists, like the other test files it guards.
  • actionlint. Clean. The only report is the existing blacksmith-* runner-label notice that ci.yml also gets, because this repo has no actionlint config.
  • This PR's own run. This PR triggers the workflow on its own branch; see the checks below.

Rollout

Merge. The first push to main uploads the baseline SARIF, and alerts appear under Security > Code scanning with the tool osv-scanner. Nothing is deployed.

Rollback

Revert this PR. To also clear the alerts, delete the osv-scanner analyses:

gh api repos/gascity/registry/code-scanning/analyses

Follow-up (not in this PR)

.github/dependabot.yml uses the npm ecosystem on a bun repo, so version PRs touch package.json but not bun.lock. Switching it to package-ecosystem: bun would keep the lock in step.

🤖 Generated with Claude Code


Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.

GitHub's dependency graph does not resolve bun.lock: its SBOM lists 36 of
the 206 packages the lock pins, so Dependabot alerts are blind to most of
this repo's dependencies.

Add .github/workflows/osv-scanner.yml (push to main, pull requests, weekly,
dispatch). It runs osv-scanner v2.7.0 (sha256-verified release binary),
which reads bun.lock natively (206 packages), uploads SARIF to code
scanning under category "osv-scanner", and fails if bun.lock ever drops out
of the scan. scripts/osv-gate.ts then fails the job on a HIGH/CRITICAL
finding (CVSS >= 7.0, or an unscored advisory labelled HIGH/CRITICAL) that
osv-scanner.toml does not accept; every waiver there must carry an
ignoreUntil date and a reason, and a lapsed waiver blocks again.

osv-scanner.toml starts empty: the scan is clean today and no risk is
accepted. Tests: scripts/osv-gate.test.ts (gate rules, allowlist format, the
CLI's exit codes, the workflow's permissions and pins); the existing
supply-chain-pins test covers the new workflow's SHA pins and its
job-scoped write grant.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gascity-infra-agent gascity-infra-agent Bot added the status/needs-review-auto PR review requested with auto approval label Nov 5, 2026
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@gascity-eddie

gascity-eddie Bot commented Nov 5, 2026

Copy link
Copy Markdown

This PR has been added to the review queue.

Track progress: https://factory.gascity.com/city/maintainer-city/runs/gcg--9223372036832388256

@gascity-eddie gascity-eddie Bot added status/reviewing and removed status/needs-review-auto PR review requested with auto approval labels Nov 5, 2026
…out scripts

Review fixes for the osv-scanner workflow:

- OSV MAL-* records (the OpenSSF malicious-packages feed) carry no CVSS
  score and no severity label, so the gate classed a known-malicious
  package as UNSCORED and passed it. A group with a MAL-* id or alias now
  rates MALICIOUS and blocks; a waiver can still accept a false positive.
  Checked against a real osv-scanner 2.7.0 report (flatmap-stream 0.1.1,
  MAL-2025-20690).
- The scan job holds security-events: write and hands its token to
  `bun install` as NODE_AUTH_TOKEN. The gate needs only smol-toml, so the
  install now runs with --ignore-scripts: no dependency lifecycle script
  runs under that token. The workflow test pins the flag.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gascity-infra-agent
gascity-infra-agent Bot merged commit 6c3c6d3 into main Nov 5, 2026
8 checks passed
@gascity-infra-agent
gascity-infra-agent Bot deleted the ci/osv-scan-bun-lock branch November 5, 2026 06:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants