npm package · MIT · Node ≥ 18

license-sentinel

A license compliance gate for npm projects, plus CycloneDX/SPDX SBOMs and a NOTICES file.

Reads every installed dependency (from node_modules or npm, pnpm and yarn lockfiles), works out each license from package.json and the LICENSE text, parses SPDX expressions and checks the result against your policy and your project's own license. The same run can write CycloneDX 1.6 and SPDX 2.3 SBOMs, attribution pages and a NOTICES file. Zero runtime dependencies.

npm i -D license-sentinel
~/project — zsh
$ npx license-sentinel --deny "AGPL-*"license-sentinel — mixed-app@2.0.0 (MIT, permissive)16 package(s) from node_modules: 16 prod, 0 dev HIGH     agpl-lib@1.0.0 is licensed AGPL-3.0-only; AGPL-3.0-only is denied by policy [denied-license]         ↳ fix: Replace the package with a compatible alternative, or add a time-boxed exception with a reason.HIGH     gpl-lib@1.0.0 is GPL-3.0-only (strong-copyleft) but the project is MIT (permissive) [incompatible-license]HIGH     proprietary@1.0.0 is UNLICENSED: no rights are granted to use, copy or distribute it [unlicensed]MEDIUM   nolicense@0.0.1 has no license: No license field and no LICENSE file [missing-license]LOW      aliased@1.0.0 declares "Apache 2.0" ("Apache 2.0" is not a valid SPDX expression; read as Apache-2.0) [invalid-spdx] 3 high, 2 medium, 4 low✖ Failing (fail-on: high).
Sample output from the license-sentinel README.

The problem

A GPL package three levels deep in an MIT product, an AGPL dependency in a SaaS, a package with no license at all: you usually find out from legal, late.

license-sentinel puts the check in CI, with a policy you control, exceptions that need a reason and expire, and the SBOM and attribution files compliance teams ask for.

Features

Every dependency source

node_modules (npm, yarn, pnpm layouts) or lockfiles: package-lock v1–v3, pnpm-lock v5/v6/v9, yarn.lock v1 and Berry.

License resolution

Reads license fields and identifies LICENSE / COPYING text; --registry fills gaps for lockfile-only scans.

SPDX expressions

AND, OR, WITH and parentheses, with deprecated ids and common misspellings normalised and flagged.

Project-aware policy

Allow / deny lists, presets, and a category check against your own project's license.

Exceptions with expiry

Each exception needs a reason and can have an expiry date, an override license or a rule scope.

SBOMs

CycloneDX 1.6 (schema-validated in CI) and SPDX 2.3 JSON.

Attribution

NOTICES file, CSV inventory, HTML and Markdown attribution pages, custom templates.

Monorepos

--workspaces audits each workspace package separately.

Usage

# Audit production deps

 npx license-sentinel

# Permissive preset, stricter gate

 npx license-sentinel --preset permissive --fail-on medium

# Lockfile only, no node_modules

 npx license-sentinel --source lockfile --registry

# SBOMs + NOTICES

 npx license-sentinel --cyclonedx bom.cdx.json --spdx bom.spdx.json --notices THIRD_PARTY_NOTICES.txt

CI / GitHub Action

permissions:
  contents: read
jobs:
  licenses:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@<sha> # v4
        with: { persist-credentials: false }
      - run: npm ci --ignore-scripts
      - uses: MrLouisWright/license-sentinel@<sha> # v1
        with:
          preset: permissive
          deny: 'AGPL-*,SSPL-1.0'
          fail-on: medium
          cyclonedx: bom.cdx.json
          notices: THIRD_PARTY_NOTICES.txt

Options & flags

FlagDescription
[dir]Project directory (default .)
--source <s>auto (default), node_modules, lockfile, or a path to a lockfile
--include-dev / --prod / --omit=devInclude devDependencies / production only (default)
--workspacesAudit each workspace package in a monorepo
--workspace-report-dir <dir>With --workspaces, write <dir>/<workspace>.json per package
--registry, --registry-url <url>Look up licenses missing from lockfiles on the registry
--preset <p>permissive, weak-copyleft or strong-copyleft
--allow <list> / --deny <list>SPDX ids, globs (GPL-*), categories (category:permissive)
--project-license <expr>Override the project's own license
-c, --config <file>JSON config (default .license-sentinel.json)
-f, --formattext (default), json, sarif, markdown
--json/--sarif/--markdown <file>Also write that report to a file
--cyclonedx <file> / --spdx <file>Write a CycloneDX 1.6 / SPDX 2.3 JSON SBOM
--notices <file>Write a third-party NOTICES / attribution file
--csv / --html / --attribution-mdCSV inventory, HTML attribution page, Markdown table
--template / --template-outRender a custom template
--reproducibleDeterministic SBOM serial number / document namespace
--fail-on <sev>critical, high (default), medium, low, info or none
--verboseList every package in text output
--list-rulesRules and default severities

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