Skip to content

GitHub Action

Two lines of YAML: execution-surface review on every dependency bump, findings in the Security tab you already use. No account, no telemetry — the Action is a thin wrapper and everything the CLI does, it does on your runner.

.github/workflows/lockwarden.yml
name: lockwarden
on:
pull_request:
paths:
- '**/package-lock.json'
- '**/pnpm-lock.yaml'
- '**/yarn.lock'
- '**/bun.lock'
permissions:
contents: read
security-events: write # SARIF upload
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # --diff needs the base ref
- uses: itsraghul/lockwarden/packages/action@v1
with:
diff-base: ${{ github.event.pull_request.base.sha }}

The workflow triggers only on PRs that touch a lockfile. With diff-base set, the Action runs audit --diff, which scores only the packages whose resolved version changed — it finishes in seconds, and findings are about what the bump introduced (a new install script, a new binding.gyp, a size explosion), not noise about what always existed. Reviewer’s guide to the findings: dependency review.

InputDefaultMeaning
commandauditaudit or check
diff-base(empty)Git ref for delta scoring (PR flow: the PR base sha); omit for a full absolute scan
thresholdhighSeverity that fails the check: low/med/high/critical
sariftrueUpload findings to the GitHub Security tab as SARIF
versionpinned per Action releaseExact CLI version the Action runs — bumped by the release workflow so the Action never floats on latest

What the wrapper actually does: sets up Node 22, runs npx --yes lockwarden@<version> <command> --ci --threshold <threshold> (plus --diff <diff-base> when set, plus --sarif redirected to a file when enabled), and uploads the SARIF via github/codeql-action/upload-sarif. Nothing else.

Two versions are in play, pinned independently:

  • The CLI version is pinned inside the Action (the version input) — each Action release pins the CLI release it was tested with. Override it only to hold back or fast-forward the CLI deliberately. Remember that vendored advisory data rides CLI releases: a pinned CLI is also pinned advisory data.

  • The Action ref is whatever you write after uses:. @v1 follows the v1 line. For maximum supply-chain rigor — the standard hardening advice for any third-party Action, this one included — pin by full commit SHA instead of tag:

    - uses: itsraghul/lockwarden/packages/action@<full-commit-sha> # v1

    A tag can be moved; a commit SHA cannot. Trade-off: SHA pins don’t receive fixes until you bump them — pair with a tool that PRs Action updates (Dependabot’s github-actions ecosystem, Renovate).

With sarif: true (the default), findings appear in Security → Code scanning on the repository and as annotations on the PR — no new UI for reviewers to learn. Severity maps Critical→error, High→warning, Med→note (Low is suppressed by default; see Scoring). Findings carry stable fingerprints so GitHub tracks them across runs rather than re-opening them each push (SARIF details).

The security-events: write permission exists solely for this upload. If you set sarif: false, drop the permission and rely on the exit code alone.

The Action fails the check when the CLI exits 1 — findings at or above threshold — and errors when the CLI exits 2 (the contract). That’s the whole integration: lockwarden detects and reports; whether a failed check blocks the merge is your branch-protection policy, not the tool’s.

lockwarden: lockfile package-lock.json not found at ref '<sha>'

The default actions/checkout is a shallow clone (fetch-depth: 1) that doesn’t contain the PR base commit. Set fetch-depth: 0 on the checkout step whenever you pass diff-base. (Fetching just the base branch also works if full history is too heavy.)

SARIF upload rejected (403 / “Resource not accessible”)

Section titled “SARIF upload rejected (403 / “Resource not accessible”)”

The workflow is missing security-events: write — add the permissions block from the example. On PRs from forks, GitHub restricts this permission by design; either accept exit-code-only behaviour for fork PRs (sarif: false) or restrict the workflow to same-repo PRs. Code scanning upload also requires the feature to be available on the repo (private repos need GitHub Advanced Security).

  • One workspace-root lockfile (npm/pnpm/yarn workspaces): nothing special — the Action runs at the repo root and audits the single lockfile.
  • Several independently-locked packages: audit analyzes one project per run, so run the Action (or raw npx with --dir) once per package — a job matrix keeps it tidy: CI recipes → monorepos.
  • Keep the paths: trigger patterns prefixed with **/ so nested lockfiles trigger the workflow.

Without diff-base the Action runs an absolute scan, which inventories existing execution surface (Med/Low mostly). Set diff-base on PRs — delta findings are the low-noise signal — and keep absolute scans for scheduled runs where a human reads the report. Why delta over absolute →

The Action is a convenience wrapper, not the integration. One line of shell does the same anywhere: CI recipes covers GitLab CI, CircleCI, Jenkins, and a generic template.