Skip to content

ci(main): standard dependency audit - #396

Merged
pacphi merged 5 commits into
mainfrom
ci/main-dependency-audit
Oct 23, 2026
Merged

pacphi merged 5 commits into
mainfrom
ci/main-dependency-audit

Conversation

@pacphi

@pacphi pacphi commented Oct 23, 2026 •

Copy link
Copy Markdown
Owner

What

Puts the dependency-audit standard on main. This PR has to merge first, so its reusable jobs also work on branches that haven't migrated yet.

Dependency Audit job (same name in all three reusable workflows)

Workflow Change
ci-v2.yml New Dependency Audit job. It runs the checked-out branch's own .github/scripts/v2/npm-audit.sh (npm audit --audit-level=high on every committed package-lock.json) on Node 24. CI v2 Required Checks now fails when it fails.
ci-v3.yml Security Audit is renamed Dependency Audit. The push-only if: and the run-audit dispatch input are gone, so the job now gates PRs. CI v3 Required Checks and CI v3 Status now fail when it fails (until now it was "non-blocking").
ci-v4.yml Renamed Dependency Audit, with --deny warnings added. The JSON and SARIF are now written under the workspace, so hashFiles() finds them and the SARIF upload runs (it never did before). The SARIF now includes denied warnings as well as vulnerabilities. v4 had no aggregate job, so this adds CI v4 Required Checks.
  • cargo-audit is pinned to 0.22.2 (cargo binstall --locked cargo-audit@0.22.2). The new jobs pin their actions by commit SHA.
  • aquasecurity/trivy-action is pinned to ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 in ci-v2.yml and ci-v3.yml, with version: v0.76.0. That is the newest Trivy at least 3 days old: v0.76.1 came out 2026-10-21, too recent.
  • .github/WORKFLOW_ARCHITECTURE.md: the job name is updated.

Transitional code (marked # transitional, to remove once every branch has migrated)

  • Rust: if <line>/audit-ignore exists, its IDs become --ignore flags, on top of <line>/.cargo/audit.toml.
  • npm: the job reads v2/npm-audit-ignore and falls back to the legacy v2/audit-ignore. It always runs whatever script the branch has:
    • Old script (v2 today): reads v2/audit-ignore in its own <GHSA-id> <lockfile-dir> format. It runs unchanged.
    • Standard script with only the legacy file: the script matches whole lines, so the job writes each line's first field to v2/npm-audit-ignore for that run.
    • Standard script with v2/npm-audit-ignore (v2.5.x, ci(v2): standard dependency audit #390): used as-is.

dependency-audit.yml (new)

  • Triggers: every Monday at 06:00 UTC, plus workflow_dispatch.
  • Permissions: contents: read, issues: write.
  • Matrix: v2, v2.5.x, v3, v3.1.x and v4. Each leg checks out its branch and runs that line's audit with the same commands as its CI job.
  • Issues: findings create or update one issue per branch, titled Dependency Audit: <branch> and labelled security. A clean run closes it.
  • Errors: a tool or registry error fails the leg and leaves the issue alone.

SECURITY.md

  • New "Dependency auditing" subsection covering the job name, commands, ignore files, where it runs, the schedule and the required check.
  • New rule under "How the branches are used": A transitive 0.x bump that is forced by an in-major security fix is allowed, and must be listed in the PR. The owner approved it on 2026-10-23.

renovate.json and .github/dependabot.yml are not touched.

Merge order and the v4 window

  • v2, v2.5.x, v3, v3.1.x stay green. I ran the new commands locally against each branch head, and the scheduled workflow ran them in CI below. All exit 0: v2 through its old script and v2/audit-ignore, v3 and v3.1.x through the legacy v3/audit-ignore flags.
  • v4 will be red until its PR merges. --deny warnings fails on two unmaintained crates: RUSTSEC-2026-0173 (proc-macro-error2) and RUSTSEC-2024-0449 (unsafe-libyaml). v4 has no legacy file to fall back on, and their documented exceptions belong in v4/.cargo/audit.toml on the v4 branch. Merge the v4 PR right after this one. Then re-run CI on any open v4 PR.

Validation

  • actionlint passes on all four changed workflows, with no new findings. The remaining ones in ci-v2.yml and ci-v3.yml were there before, and one in ci-v4.yml is gone.
  • yamllint -c .yamllint.yml, prettier --check and markdownlint all pass.
  • dependency-audit.yml runs. A schedule- and dispatch-only workflow can't be dispatched from a branch before it is on the default branch: gh workflow run returns 404. To register it, I added a temporary push trigger for this branch and reverted it in the next commit, so the file is back to its final form.
    • Run 40001577142 (push): v2, v2.5.x, v3 and v3.1.x were clean. v4 had findings and opened Dependency Audit: v4 #393 (Dependency Audit: v4, security).
    • The first push run (40001365296) found a bug, fixed here: Actions runs bash with -e, which ended the audit step before it recorded its result.
    • Run 40001696446 is gh workflow run dependency-audit.yml --ref ci/main-dependency-audit on the final file, and it succeeded. Issue writes were allowed on the non-default ref. Results matched, and the v4 leg updated Dependency Audit: v4 #393 rather than opening a duplicate.
  • Not verifiable before merge: the reusable ci-v2.yml, ci-v3.yml and ci-v4.yml jobs only run from branches after this merges, because the shims call @main.

🤖 Generated with Claude Code

- ci-v2: add `Dependency Audit`, which runs the checked-out branch's
  .github/scripts/v2/npm-audit.sh (npm audit --audit-level=high); the
  Required Checks job now fails when it fails.
- ci-v3: rename Security Audit to `Dependency Audit` and drop the
  push-only `if:` (and the run-audit input), so it gates pull requests;
  Required Checks and Status now fail when it fails.
- ci-v4: rename to `Dependency Audit`, add --deny warnings, write the
  JSON and SARIF under the workspace so hashFiles() finds them, include
  denied warnings in the SARIF, and add a CI v4 Required Checks job.
- All three pin cargo-audit 0.22.2 / actions by SHA. Rust jobs also
  honour a legacy <line>/audit-ignore (marked transitional) so branches
  not yet migrated to .cargo/audit.toml stay green.
- Pin aquasecurity/trivy-action to the v0.36.0 commit with Trivy v0.76.0.
- Add dependency-audit.yml: weekly (Mon 06:00 UTC) and on dispatch,
  audits v2, v2.5.x, v3, v3.1.x and v4 and keeps one `security` issue
  per branch titled "Dependency Audit: <branch>".
Add a "Dependency auditing" subsection (job name, commands, ignore
files, schedule, required check) and the rule that a transitive 0.x
bump forced by an in-major security fix is allowed and must be listed
in the PR (approved by the owner on 2026-10-23).
…ash -e

- ci-v2 and dependency-audit.yml (transitional): when a branch has the
  standard npm-audit.sh but only the legacy "<GHSA-id> <lockfile-dir>"
  v2/audit-ignore, write its first fields to v2/npm-audit-ignore for the
  run. A branch whose old script reads v2/audit-ignore runs unchanged.
- dependency-audit.yml: Actions runs bash with -e, which ended the audit
  step before it recorded findings; turn it off for that step.
….yml (reverted next commit)"

This reverts commit 0fd2ceb.
@pacphi
pacphi merged commit 952c5b8 into main Oct 23, 2026
20 of 21 checks passed
@pacphi
pacphi deleted the ci/main-dependency-audit branch October 23, 2026 20:20
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