GitHub Actions (package-scanner-ci)

Use package-scanner-ci to send lockfiles and package.json to the hosted PackageScanner service on pull requests and pushes.

Repository (source and docs)
What this action does

It reads supported lockfiles and/or package.json from the workspace and forwards them to the PackageScanner CI API. It does not analyze dependencies locally—it is a thin CI client.

  • Fail the job on malware by default, and on High/Critical vulnerabilities by default
  • Auto-detect lockfiles so you can start with a minimal workflow
  • Expose analysis-id, malware counts, and severity-specific vulnerability counts as outputs
Quick start

Step 1: Reference the action

Pin the published GitHub Action like this.

uses: Kazuki-tam/package-scanner-ci@v1

Minimal workflow

After setting permissions and checking out the repo, run the scan step.

permissions:
  contents: read

jobs:
  package-scanner:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - id: scan
        uses: Kazuki-tam/package-scanner-ci@v1

      - run: |
          echo "analysis=${{ steps.scan.outputs.analysis-id }}"
          echo "malware=${{ steps.scan.outputs.malware-count }}"
          echo "vulns=${{ steps.scan.outputs.vulnerability-count }}"
          echo "low=${{ steps.scan.outputs.vulnerability-low-count }}"
          echo "moderate=${{ steps.scan.outputs.vulnerability-moderate-count }}"
          echo "high=${{ steps.scan.outputs.vulnerability-high-count }}"
          echo "critical=${{ steps.scan.outputs.vulnerability-critical-count }}"

Step 2: Example with triggers

Run only when dependency manifests change (adjust paths for your repo).

name: PackageScanner

on:
  pull_request:
    paths:
      - "package.json"
      - "package-lock.json"
      - "pnpm-lock.yaml"
      - "yarn.lock"
      - "bun.lock"
  push:
    branches:
      - main

permissions:
  contents: read

jobs:
  package-scanner:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - id: scan
        uses: Kazuki-tam/package-scanner-ci@v1

      - run: |
          echo "analysis=${{ steps.scan.outputs.analysis-id }}"
          echo "malware=${{ steps.scan.outputs.malware-count }}"

Step 3: Understand failures

By default the step fails when malware is found, and when High/Critical vulnerabilities are present (tune with fail-on-vulnerability-severity).

Default failure behavior
By default, the step fails when either condition is true:
  • Malware findings are present (when fail-on-malware is true)
  • At least one vulnerability is High or Critical (default fail-on-vulnerability-severity is high)

You can change the vulnerability threshold with fail-on-vulnerability-severity.

  • off: never fail because of vulnerabilities
  • low: fail on any vulnerability
  • moderate: fail on moderate, high, or critical
  • high: fail on high or critical (default)
  • critical: fail only on critical
Common examples
Monorepos, output-only runs, and PR comments.

Scan a monorepo subdirectory

Set working-directory when manifests live under apps/*.

- id: scan
  uses: Kazuki-tam/package-scanner-ci@v1
  with:
    working-directory: "apps/web"

Read outputs without failing the job

Set fail-on-malware to false and fail-on-vulnerability-severity to off to keep the job green while reading outputs.

- id: scan
  uses: Kazuki-tam/package-scanner-ci@v1
  with:
    fail-on-malware: "false"
    fail-on-vulnerability-severity: "off"

- run: echo "analysis=${{ steps.scan.outputs.analysis-id }} malware=${{ steps.scan.outputs.malware-count }} vulns=${{ steps.scan.outputs.vulnerability-count }}"

Post a PR comment

Example using actions/github-script to format outputs and post a comment.

- uses: actions/github-script@v7
  if: github.event_name == 'pull_request'
  with:
    script: |
      const body = [
        "## PackageScanner",
        `- Malware: ${{ steps.scan.outputs.malware-count }}`,
        `- Low: ${{ steps.scan.outputs.vulnerability-low-count }}`,
        `- Moderate: ${{ steps.scan.outputs.vulnerability-moderate-count }}`,
        `- High: ${{ steps.scan.outputs.vulnerability-high-count }}`,
        `- Critical: ${{ steps.scan.outputs.vulnerability-critical-count }}`,
      ].join("\n");
      await github.rest.issues.createComment({
        owner: context.repo.owner,
        repo: context.repo.repo,
        issue_number: context.issue.number,
        body,
      });
Requirements
  • Run actions/checkout before this action so files exist in the workspace
  • Self-hosted runners must have node on PATH
  • Node 18.17+
  • Allow outbound HTTPS to https://www.package-scanner.dev
Main inputs / outputs
Public interface from action.yml (excerpt).
  • working-directory: Base directory for resolving lockfile and package-json paths. Default: .
  • lockfile: Optional explicit path; otherwise auto-detects common lockfile names.
  • package-json: Optional path; defaults to package.json when present.
  • package-manager: npm, pnpm, yarn, or bun when it cannot be inferred from the lockfile name.
  • fail-on-malware: Exit with failure when malware is reported. Default: true.
  • fail-on-vulnerability-severity: off, low, moderate, high, or critical. Default: high.
  • enable-metadata-check: Enable npm registry metadata checks (requires package.json). Default: false.
  • Outputsanalysis-id, malware-count, vulnerability-count, and per-severity vulnerability counts. A Markdown summary may be written to the job summary when available.
Notes
Review before you enable this in CI.
  • Transmitted data can include raw lockfile/package.json contents, inferred package manager, and the enable-metadata-check flag.
  • Paths must resolve inside the checked-out workspace; traversal outside the workspace is rejected.
  • If your policy forbids sending private dependency contents to a third-party host, decide whether this hosted API is appropriate for your organization.
  • See the repository docs (CONSUMER-GUIDE, API-SPEC) and examples/consumer-workflow.yml for more detail.