GitHub Packages · MIT · Node ≥ 18

sbom-diff-sentinel

See exactly what a pull request changes in your software bill of materials, and block the risky changes.

SBOM diff gate: compares CycloneDX 1.4-1.6 / SPDX 2.3 SBOMs or git refs, reports added, removed, upgraded and downgraded components plus license, supplier and hash changes, checks OSV.dev for new vs fixed vulns, and enforces policy. Text/JSON/SARIF/Markdown, GitHub Action.

  1. 1 Point the @mrlouiswright scope at GitHub Packages in .npmrc

    @mrlouiswright:registry=https://npm.pkg.github.com
  2. 2 Install

    npm i -D @mrlouiswright/sbom-diff-sentinel
Installing from GitHub Packages needs a token

Published to GitHub Packages, not npmjs.com. GitHub Packages needs a GitHub token with read:packages to install, even for public packages: add //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} to .npmrc or run npm login --registry=https://npm.pkg.github.com.

~/project — zsh
$ npx sbom-diff-sentinel base.cdx.json head.spdx.json --offlineSBOM diff: base.cdx.json (8) → head.spdx.json (10) Added (3)  + axios@0.21.0 MIT  + copyleft-lib@1.0.0 AGPL-3.0-only  + dual@2.0.0 MIT OR GPL-3.0-only Removed (1)  - left-pad@1.3.0 Upgraded (1)  ↑ lodash 4.17.20 → 4.17.21 ...           ↳ Review the new license terms 6 change(s): +3 -1 ↑1 ↓1; vulns: 0 new, 0 fixed (skipped (offline)); 3 high, 2 medium, 1 low
Real output from running sbom-diff-sentinel locally on a test fixture.

Why it exists

sbom-diff-sentinel compares two SBOMs, or your project at a git ref against the working tree. It reports components that were added, removed, upgraded or downgraded, plus license, supplier and hash changes. It checks the added and changed components against OSV.dev and splits the results into new and fixed vulnerabilities, each with a severity. Then it applies a policy: fail on new vulnerabilities at or above a severity, downgrades, new copyleft licenses or oversized changes.

- Reads CycloneDX 1.4–1.6 JSON and SPDX 2.3 JSON - Generates SBOMs from npm, pnpm and yarn lockfiles with license-sentinel - Text, JSON, SARIF and Markdown output (the Markdown suits PR comments and job summaries) - CLI, library and GitHub Action. Node.js 18+, one zero-dependency runtime dependency

Features

new-vulnerability

An added or changed component has an OSV advisory that the base didn't have (matched by ID and aliases) (default: the advisory's severity)

copyleft-license

A new dependency, or a license change, brings in copyleft (`--copyleft weak\ (default: high)

hash-changed

Same name and version, different hash: a republished or tampered package, or a different mirror (default: high)

too-many-changes

More component changes than --max-changes (default: high)

osv-error

The OSV lookup failed, so the check can't silently pass. Use --offline to skip it on purpose (default: high)

downgrade

A component moved to a lower version (default: medium (--deny-downgrades raises it to high))

supplier-changed

The supplier or publisher changed (default: medium)

license-changed

Any license change (default: low)

Usage

# project at origin/main vs working tree

 npx sbom-diff-sentinel --base origin/main

# two SBOM files (formats can be mixed)

 npx sbom-diff-sentinel base.cdx.json head.spdx.json

# SBOM file vs the current project

 npx sbom-diff-sentinel base.cdx.json

# write a CycloneDX 1.5 SBOM for the project

 npx sbom-diff-sentinel --generate bom.cdx.json

CI / GitHub Action

on: pull_request
permissions:
  contents: read
jobs:
  sbom-diff:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0, persist-credentials: false }
      - uses: MrLouisWright/sbom-diff-sentinel@v1
        id: sbom
        with:
          fail-on: high          # base defaults to origin/<PR base branch>
          max-changes: '50'

Options & flags

FlagDescription
--base <file|ref>Base SBOM file, or a git ref (e.g. origin/main) to generate it from
--head <file|dir>Head SBOM file or project directory (default: --project)
-C, --project <dir>Project directory for generation and git refs (default: .)
--include-devInclude devDependencies when generating
--offlineSkip the OSV.dev vulnerability lookup
--osv-url <url>OSV API base URL (default: https://api.osv.dev)
--timeout <ms>OSV request timeout (default: 15000)
--fail-on <sev>critical | high | medium | low | info | none (default: high)
--copyleft <level>Flag new copyleft: weak | strong | network | none (default: strong)
--max-changes <n>Fail when more than n components change
--deny-downgradesTreat downgrades as high severity
--config <file>Config file (default: .sbom-diff-sentinel.json or package.json "sbom-diff-sentinel")
--format <fmt>Stdout format: text | json | sarif | markdown (default: text)
--json <file>Also write a JSON report
--sarif <file>Also write a SARIF 2.1.0 report
--markdown <file>Also write a Markdown report (PR comment / job summary)
--no-fixesHide fix suggestions --no-color Disable colours
-q, --quietOnly print the summary line

Full reference, config file format and API in the README.

Support this project

Support open-source security tools

I build free, open-source tools that help developers ship safer websites. Every coffee helps keep them maintained, documented and free for everyone.

Buy me a coffee (opens Stripe in a new tab)

Secure checkout by Stripe

Portrait of Louis Wright

About the author

Louis Wright

Cyber security researcher and software engineer based in the UK.

More tools by Louis Wright

58 tools

Sentinels security scanners & CI gates · 19