Skip to content

feat(security): run npm audit auto-fix on all branches and scheduled scans - #116

Merged
tehw0lf merged 3 commits into
mainfrom
feature/npm-audit-autofix-scheduled
Jul 25, 2026
Merged

feat(security): run npm audit auto-fix on all branches and scheduled scans#116
tehw0lf merged 3 commits into
mainfrom
feature/npm-audit-autofix-scheduled

Conversation

@tehw0lf

@tehw0lf tehw0lf commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Problem

The npm audit auto-fix only ran for Dependabot PRs — gated on
github.actor == 'dependabot[bot]' plus a non-empty head_ref. Two gaps:

  1. Scheduled scans (daily cron in yaft/wp2md/color) detected vulnerabilities
    but never fixed them — a new advisory sat until some Dependabot PR happened
    to touch the same lockfile.
  2. Regular feature branches got nothing: push a commit that trips
    npm audit, get a red scan, fix it by hand.

Change

npm-audit-autofix.yml now has two modes, both dispatched from
security-scan-source.yml:

branch scheduled
Trigger any PR branch in this repo (Dependabot and feature branches) schedule / workflow_dispatch
PR base the triggering branch default branch (or audit_fix_base_branch)
Fix branch audit-fix/<branch>-<sha> (per commit) audit-fix/scheduled (stable)
Existing PR new PR each push edited in place, branch force-pushed

branch is the everyday path: npm audit fails on your feature branch, a
fix PR is opened against your branch. Merge it and carry on — the fix reaches
main with your own PR. This is the old dependabot mode with the actor check
removed; the mechanics were already right, only the gating and the
Dependabot-specific PR wording changed (the body now adapts to the actor).

scheduled is the low-intervention path: cron finds the advisory, fixes it,
leaves one mergeable PR against main. The fix branch is rebuilt from base
each run, so later runs force-push and gh pr edit the same PR instead of
piling up duplicates.

New inputs on security-scan-source.yml:

enable_npm_audit_autofix: true  # kill switch for both modes
audit_fix_base_branch: ""       # default: repo default branch

Deliberately not done

Fork PRs are skipped, guarded by head.repo.full_name == github.repository.
Their GITHUB_TOKEN is read-only, so the push cannot succeed — skipping beats
failing. Covering them needs pull_request_target, which runs untrusted PR code
with write permissions.

No --force. Only semver-compatible updates land, package.json is never
touched — 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, wp2md and color already grant contents: write
and pull-requests: write, pull @main, and trigger on pull_request;
build-test-publish.yml already falls back to github.head_ref.

Validation

  • actionlint .github/workflows/*.yml → exit 0
  • YAML parse check on both modified workflows → OK
  • Branch-naming logic extracted and tested for both modes: Dependabot branches,
    feature/x, fix/x, flat names, and the default-branch fallback
  • Generated refs verified against real git — nested slashes coexist fine

Note: reusable-workflow behaviour is only fully verifiable after merge to
main, since consumers reference @main.

Summary by CodeRabbit

  • New Features
    • Added a two-mode npm audit auto-fix workflow for PR branches and scheduled/manual runs.
    • Enhanced the source security scan to optionally enable auto-fix and set the scheduled PR target branch.
    • Auto-fix can now reuse an existing matching fix pull request when present.
  • Bug Fixes
    • Improved validation, fix-branch/PR targeting behavior, and PR detection/editing logic.
  • Documentation
    • Updated CLAUDE.md with trigger rules, configuration, permissions, and PR/branch behavior details.

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.
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 27b9a637-ce69-4eae-afea-0bca3ad90bcb

📥 Commits

Reviewing files that changed from the base of the PR and between 2d17c64 and f73b2af.

📒 Files selected for processing (1)
  • .github/workflows/npm-audit-autofix.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/npm-audit-autofix.yml

📝 Walkthrough

Walkthrough

The 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.

Changes

Npm audit autofix modes

Layer / File(s) Summary
Workflow contracts and job wiring
.github/workflows/npm-audit-autofix.yml, .github/workflows/security-scan-source.yml
Adds mode, base-branch, and enablement inputs; exposes autofix outputs from branch or scheduled jobs; and wires both execution paths.
Mode-specific branch and PR execution
.github/workflows/npm-audit-autofix.yml
Validates mode-specific inputs, selects checkout refs, computes and pushes mode-specific branches, generates PR metadata, and updates or creates matching pull requests.
Autofix workflow documentation
CLAUDE.md
Documents dispatch modes, branch and pull request behavior, audit-fix constraints, configuration, permissions, and fork handling.

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
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: npm audit auto-fix now runs for branches and scheduled scans.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/npm-audit-autofix-scheduled

Comment @coderabbitai help to get the list of available commands.

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.
@tehw0lf tehw0lf changed the title feat(security): run npm audit auto-fix on scheduled scans feat(security): run npm audit auto-fix on all branches and scheduled scans Jul 25, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between ded1d66 and 0437eeb.

📒 Files selected for processing (3)
  • .github/workflows/npm-audit-autofix.yml
  • .github/workflows/security-scan-source.yml
  • CLAUDE.md

Comment thread .github/workflows/npm-audit-autofix.yml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Validate base_branch before checkout.

A malformed scheduled-mode base_branch currently fails later in checkout without the workflow’s categorized invalid-input exit. Validate a non-empty value in this step and exit 3 on 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 win

Declare 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: add contents: write and pull-requests: write to branch-audit-fix.
  • .github/workflows/security-scan-source.yml#L249-L265: add the same permissions to scheduled-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

📥 Commits

Reviewing files that changed from the base of the PR and between 0437eeb and 2d17c64.

📒 Files selected for processing (3)
  • .github/workflows/npm-audit-autofix.yml
  • .github/workflows/security-scan-source.yml
  • CLAUDE.md

Comment thread .github/workflows/npm-audit-autofix.yml
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.
@tehw0lf
tehw0lf merged commit 88cd07b into main Jul 25, 2026
3 checks passed
@tehw0lf
tehw0lf deleted the feature/npm-audit-autofix-scheduled branch July 25, 2026 21:26
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