feat(security): run npm audit auto-fix on all branches and scheduled scans - #116
Conversation
The auto-fix was gated on github.actor == 'dependabot[bot]' and a PR
head_ref, so scheduled security scans found vulnerabilities but never
fixed them. A newly disclosed advisory sat until the next Dependabot
run touched the same lockfile.
Add a 'scheduled' mode that opens the fix PR against the default
branch instead of a Dependabot branch, so it can be merged directly.
It reuses a stable audit-fix/scheduled branch and edits the existing
PR rather than opening a new one on every cron tick.
Both modes keep npm audit fix without --force: only semver-compatible
updates, package.json untouched, remaining findings reported in the
PR body.
Also move inline ${{ }} interpolations in run blocks to env vars.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe reusable npm audit autofix workflow now supports branch and scheduled/manual modes. Caller inputs and outputs were expanded, scheduled runs reuse a stable fix branch and pull request, and branch-based runs support non-Dependabot pull requests subject to repository checks. ChangesNpm audit autofix modes
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant SecurityScanSource
participant NpmAuditAutofix
participant Git
participant GitHubPullRequests
SecurityScanSource->>NpmAuditAutofix: invoke with selected mode and branch inputs
NpmAuditAutofix->>Git: checkout ref and push computed fix branch
NpmAuditAutofix->>GitHubPullRequests: find open PR for fix branch and base branch
GitHubPullRequests-->>NpmAuditAutofix: existing PR or no matching PR
NpmAuditAutofix->>GitHubPullRequests: edit existing PR or create new PR
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
The auto-fix only triggered for Dependabot PRs and scheduled runs, so a feature branch whose commit broke npm audit got a red scan and no fix. Rename mode 'dependabot' to 'branch' and drop the actor check: any PR branch in this repo now gets a fix PR against itself, per commit. The mechanics were already correct for this, only the gating and the Dependabot-specific PR wording needed to change - the body now adapts based on the actor. Fork PRs are excluded via head.repo.full_name: their GITHUB_TOKEN is read-only so the push would fail, and covering them would require pull_request_target, which runs untrusted code with write permissions.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/npm-audit-autofix.yml:
- Around line 101-108: Update the checkout step’s ref expression to use the
repository’s default branch when the selected scheduled-mode branch value is
empty, mirroring the fallback logic in the “compute branch names” step. Preserve
the existing dependabot head_ref and base_branch selection while ensuring manual
scheduled runs checkout the default branch rather than the triggering ref/SHA.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 9d9484f4-2c7b-4041-ad6e-67f2fe2e2f9c
📒 Files selected for processing (3)
.github/workflows/npm-audit-autofix.yml.github/workflows/security-scan-source.ymlCLAUDE.md
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
.github/workflows/npm-audit-autofix.yml (1)
82-100: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winValidate
base_branchbefore checkout.A malformed scheduled-mode
base_branchcurrently fails later in checkout without the workflow’s categorized invalid-input exit. Validate a non-empty value in this step and exit3on failure.As per coding guidelines, “Use input validation and sanitization, validate secrets early, and use categorized exit codes for missing secrets and invalid input.”
Proposed fix
env: MODE: ${{ inputs.mode }} HEAD_REF: ${{ inputs.head_ref }} + BASE_BRANCH: ${{ inputs.base_branch }} run: | case "$MODE" in branch) @@ scheduled) + if [ -n "$BASE_BRANCH" ] && ! git check-ref-format --branch "$BASE_BRANCH" >/dev/null; then + echo "::error::invalid base_branch '$BASE_BRANCH'" + exit 3 + fi ;;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/npm-audit-autofix.yml around lines 82 - 100, Extend the validate inputs step to expose base_branch and require it to be non-empty before checkout, including for scheduled mode. On missing base_branch, emit a clear categorized input error and exit with status 3; preserve the existing MODE and HEAD_REF validation behavior.Source: Coding guidelines
.github/workflows/security-scan-source.yml (1)
228-247: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winDeclare the exact write scopes for both reusable-workflow calls.
Both callers inherit repository-default token permissions, which can be overly broad or insufficient for the callee’s required branch push and PR operations.
.github/workflows/security-scan-source.yml#L228-L247: addcontents: writeandpull-requests: writetobranch-audit-fix..github/workflows/security-scan-source.yml#L249-L265: add the same permissions toscheduled-audit-fix.As per coding guidelines, “Use minimal GitHub Actions permissions.”
Proposed fix
branch-audit-fix: needs: scan_source + permissions: + contents: write + pull-requests: write # any PR branch in this repo - Dependabot and regular feature branches @@ scheduled-audit-fix: needs: scan_source + permissions: + contents: write + pull-requests: write # scheduled/manual runs have no PR branch: fix against the default branch🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/security-scan-source.yml around lines 228 - 247, Add explicit contents: write and pull-requests: write permissions to both reusable-workflow calls, branch-audit-fix and scheduled-audit-fix, in .github/workflows/security-scan-source.yml at lines 228-247 and 249-265. Keep the permissions scoped to these jobs and leave all other workflow behavior unchanged.Sources: Coding guidelines, Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/npm-audit-autofix.yml:
- Around line 8-10: Update the workflow description near the scheduled-mode
behavior to state that scheduled pull requests target the configurable
base_branch input, defaulting to the repository’s default branch only when
base_branch is empty. Keep the existing triggering-branch behavior for
non-scheduled runs unchanged.
---
Outside diff comments:
In @.github/workflows/npm-audit-autofix.yml:
- Around line 82-100: Extend the validate inputs step to expose base_branch and
require it to be non-empty before checkout, including for scheduled mode. On
missing base_branch, emit a clear categorized input error and exit with status
3; preserve the existing MODE and HEAD_REF validation behavior.
In @.github/workflows/security-scan-source.yml:
- Around line 228-247: Add explicit contents: write and pull-requests: write
permissions to both reusable-workflow calls, branch-audit-fix and
scheduled-audit-fix, in .github/workflows/security-scan-source.yml at lines
228-247 and 249-265. Keep the permissions scoped to these jobs and leave all
other workflow behavior unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6d9295d1-41a9-4a71-8000-0dd9db94fea7
📒 Files selected for processing (3)
.github/workflows/npm-audit-autofix.yml.github/workflows/security-scan-source.ymlCLAUDE.md
With mode=scheduled and no base_branch input, the checkout ref expression evaluated to an empty string. actions/checkout then falls back to the ref of the triggering event, not the default branch - so a workflow_dispatch from another branch would fix that branch while opening the PR against the default branch. Apply the same default_branch fallback the compute-branch-names step already uses, keeping checkout and PR base in sync. Reported by CodeRabbit on #116.
Problem
The npm audit auto-fix only ran for Dependabot PRs — gated on
github.actor == 'dependabot[bot]'plus a non-emptyhead_ref. Two gaps:but never fixed them — a new advisory sat until some Dependabot PR happened
to touch the same lockfile.
npm audit, get a red scan, fix it by hand.Change
npm-audit-autofix.ymlnow has two modes, both dispatched fromsecurity-scan-source.yml:branchscheduledschedule/workflow_dispatchaudit_fix_base_branch)audit-fix/<branch>-<sha>(per commit)audit-fix/scheduled(stable)branchis the everyday path:npm auditfails on your feature branch, afix PR is opened against your branch. Merge it and carry on — the fix reaches
mainwith your own PR. This is the olddependabotmode with the actor checkremoved; the mechanics were already right, only the gating and the
Dependabot-specific PR wording changed (the body now adapts to the actor).
scheduledis the low-intervention path: cron finds the advisory, fixes it,leaves one mergeable PR against
main. The fix branch is rebuilt from baseeach run, so later runs force-push and
gh pr editthe same PR instead ofpiling up duplicates.
New inputs on
security-scan-source.yml:Deliberately not done
Fork PRs are skipped, guarded by
head.repo.full_name == github.repository.Their
GITHUB_TOKENis read-only, so the push cannot succeed — skipping beatsfailing. Covering them needs
pull_request_target, which runs untrusted PR codewith write permissions.
No
--force. Only semver-compatible updates land,package.jsonis nevertouched — that is what keeps these PRs safe to merge on green CI. Findings
needing a major upgrade stay open and are listed in the PR body.
Consumer repos
No changes needed.
yaft,wp2mdandcoloralready grantcontents: writeand
pull-requests: write, pull@main, and trigger onpull_request;build-test-publish.ymlalready falls back togithub.head_ref.Validation
actionlint .github/workflows/*.yml→ exit 0feature/x,fix/x, flat names, and the default-branch fallbackNote: reusable-workflow behaviour is only fully verifiable after merge to
main, since consumers reference@main.Summary by CodeRabbit