depcurfew v1.6.1

GitHub Action

The action runs depcurfew doctor, prints the report to the job log, shows each finding as an annotation on its file and in a table in the job summary, each with how to fix it, uploads the SARIF report to code scanning and fails the job when doctor finds an error, or also a warning when doctor.failOn in depcurfew.json is warning (the input fail-on is empty by default and follows it) or the input fail-on is warning (as depcurfew doctor --fail-on warning); fail-on: error fails on errors only, whatever the policy says, and the depcurfew doctor check fails or passes the same way. The log and the job summary also say what was checked: the tools found, the files read and every check with its result (passed, the problems it found, skipped because it needs depcurfew.json, or not applicable to the project). Without depcurfew.json the action runs only the rules that need no policy; npx depcurfew doctor on the command line also shows what the default policy would change. A clean run adds a notice with the same list ("No problems found in 7 files for npm 11.21.1 (package.json). 14 checks: 9 passed, 5 not applicable."), so it is not mistaken for one that did nothing. Code scanning lists only alerts, so its entry stays empty when there is nothing to report; next to it, in the Checks tab of a pull request, the action adds the check "depcurfew doctor" with the result, the table of checks and the findings as annotations on their lines (at most 100, errors first; a finding about a whole file is shown on its first line). It needs checks: write, which the example below grants; without it the step only says so, as a warning in the log. The lines the action writes about its own run start with depcurfew: and their level (error, warning or note); its notes and warnings are also annotations of the same level (unless annotations is false), and its errors are the error annotation of the failing step. The check goes on the commit the run checked: the head of the pull request for pull_request (where GITHUB_SHA is a merge commit), else GITHUB_SHA, so under pull_request_target, which checks out the base branch, it never marks the head of the pull request as checked. A workflow that runs on both push and pull_request checks the same commit twice: the second run updates the entry of the first one instead of adding another, unless both run at the same moment, since GitHub has no way to look for an entry and add one in a single step. Annotations cannot be removed from an entry, so when the first entry has annotations other than the second run's findings, the second run adds a new entry and marks the first one as replaced (neutral, with a title that says so), rather than leave findings that no longer hold under the new result. It runs from its own checkout, with nothing to install, and sets up Node.js 22 only when the runner has an older version.

Pin it to a full commit SHA, like every action in your workflows; the example pins the commit of a release, and the comment names its tag. Pin a release at least as new as the depcurfew your project uses elsewhere (in package.json, the hook or npx): an older Action reports policy fields it does not know as an invalid policy, such as doctor and projects, which are new in 1.3.0 and which depcurfew init 1.3.0 writes, and names it does not know, such as composer: names (new in 1.4.0); it does not check Composer projects before 1.4.0 and ignores inputs it does not have, such as osv (new in 1.4.0). The example pins the release that was current when this README was written; when you install a newer depcurfew, pin the commit of its tag (git ls-remote https://github.com/DevXord/depcurfew refs/tags/v<version>). If the repository cannot use code scanning, set upload-sarif: false; the findings stay in the job log. osv: true adds the rule known-malicious, as depcurfew doctor --osv does: the runner then sends the locked package versions to api.osv.dev (see Known malicious versions).

name: depcurfew

on:
  push:
  pull_request:

jobs:
  doctor:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    permissions:
      security-events: write
      # The depcurfew doctor check with the result in the Checks tab:
      checks: write
      # Only needed in private repositories:
      actions: read
      contents: read
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: DevXord/depcurfew@cc7f3752f959bf831a11c7365de9dd307029d458 # v1.6.0
InputDefaultDescription
directory.Directory to check, relative to the workspace.
sarif-filedepcurfew.sarifWhere to write the SARIF report, relative to the workspace; a path outside it works too.
upload-sariftrueUpload the SARIF report to GitHub code scanning. The job needs the security-events write permission.
categorydepcurfewCode scanning category of the upload, to tell several depcurfew runs in one workflow apart.
fail-onemptyWhich findings fail the step and the depcurfew doctor check. Empty (the default) follows doctor.failOn in depcurfew.json, which depcurfew init sets to warning, and fails on errors only without it; error or warning overrides the policy, and warning makes warnings fail them too, as depcurfew doctor --fail-on warning does. Notes never do. Any other value fails the step.
fail-on-errortrueDeprecated, use fail-on. false keeps the step from failing on findings at all, whatever fail-on says, and makes the depcurfew doctor check neutral instead of failed.
annotationstrueShow the findings as annotations on the files, each with how to fix it, or one notice when there are none, which lists every check and its result. The notes and warnings of the action about the run itself (a directory checked with the root that lists it under projects, a depcurfew doctor check that could not be added) are annotations too, of the same level as in the log. GitHub shows a limited number per step; the log lists every finding. Turn off when code scanning already shows them.
job-summarytrueAdd a table of the findings, each with how to fix it, and what was checked (tools, files read, every check with its result) to the job summary.
check-runtrueAdd a check named "depcurfew doctor" to the commit, with the result, every check and the findings as annotations on the files (at most 100, errors first), shown next to the code scanning entry in the Checks tab of a pull request. A later run on the same commit, such as push and pull_request of one commit, updates it instead of adding a second one. The job needs the checks write permission; without it the step only says so, as a warning in the log.
github-token${{ github.token }}Token for the depcurfew doctor check; the workflow token by default.
osvfalsetrue also looks every locked package version up in OSV.dev and reports a known malicious version as an error (the rule known-malicious, as depcurfew doctor --osv does); it sends the package names and versions to api.osv.dev. false (the default) sends nothing. A version OSV.dev did not answer for gives a warning. Any other value fails the step.
OutputDescription
errorsNumber of findings with level error.
warningsNumber of findings with level warning.
notesNumber of findings with level note.
sarif-filePath of the SARIF report, relative to the workspace when it is inside it, otherwise absolute; empty when doctor could not run or the report could not be written.

Other CI systems

The action works only on GitHub. On GitLab CI or any other CI, install the project's dependencies without running their install scripts, so nothing from the lockfile runs before doctor has checked it, then run the depcurfew version the lockfile pins; the job fails when doctor finds an error, or a warning when doctor.failOn is warning (exit code 1):

depcurfew:
  image: node:22
  script:
    - npm ci --ignore-scripts
    - npx --no depcurfew doctor

--no makes npx fail instead of downloading the latest depcurfew when the project does not have it; in CI npx otherwise downloads without asking. With pnpm, Yarn or Bun, use their frozen-lockfile install with install scripts turned off instead of npm ci --ignore-scripts.

depcurfew doctor --json and --sarif write the findings for other tools; set FORCE_COLOR=1 if the CI log shows colors.