Open-source license compliance

Before adding dependencies, identify copyleft, patent clauses, and notice obligations; produce allowlists and exception-approval paths.

The SKILL embeds an org-level allow / legal review / deny license table and requires scan output to match the lockfile; UNKNOWN or dual licensing needs human confirmation.

Binary distribution vs SaaS changes source-offer, copyright, and NOTICE aggregation requirements; the agent should separate delivery shape and list files that must ship with the artifact.

Tie to SBOM: license field changes trigger compliance review; model output must remind readers this is not legal advice—escalate major decisions to counsel.

  • Do not mix GPL-family static linking with closed-source strategy without review.
  • Keep third-party acknowledgements in docs and UI in sync with the dependency list.
  • Record each policy exception and its re-review date.

Scan tool commands and CI blocking configuration

license-checker / FOSSA CLI scanning

# license-checker (Node.js projects)
npx license-checker --production \
  --onlyAllow 'MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;CC0-1.0' \
  --excludePackages 'myapp@1.0.0' \
  --json > license-report.json

# List all licenses (with dependency tree)
npx license-checker --production --csv > licenses.csv

# FOSSA CLI scan (requires FOSSA_API_KEY)
fossa analyze --branch main
fossa test --timeout 600  # non-zero exit means policy violation

# Python projects — pip-licenses
pip install pip-licenses
pip-licenses --format=json \
  --with-urls \
  --with-authors \
  --output-file=licenses.json

# Auto-generate NOTICE file
npx license-checker --production \
  --customFormat='{"name":"","version":"","licenses":"","copyright":""}' \
  --out NOTICE \
  --customPath notice-template.json

CI blocking for GPL libraries (GitHub Actions)

# .github/workflows/license-check.yml
name: License Compliance
on: [pull_request]
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - run: npm ci --production
      - name: Check licenses (deny GPL)
        run: |
          npx license-checker --production \
            --onlyAllow 'MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;CC0-1.0;Unlicense' \
            --excludePackages 'approved-exception@1.0.0' || \
            (echo "::error::Disallowed license detected, check license-report.json" && exit 1)
      - name: Upload report
        uses: actions/upload-artifact@v4
        with:
          name: license-report
          path: license-report.json

Compliance flow (lockfile → scan → SBOM)

  [ Align lockfile / build graph with org allowlist ]
        │
        ▼
  ┌─────────────┐     Parse SPDX License Expressions; flag UNKNOWN / OR / AND
  │ Dependency scan │──── Conflicts: copyleft × closed-source distribution, patent grants, additional obligations
  └─────────────┘
        │
        ▼
  ┌─────────────┐     CycloneDX / SPDX JSON: licenseDeclared / licenseConcluded per component
  │  SBOM output  │──── Version drift: diff license fields → trigger compliance review ticket
  └─────────────┘
        │
        ▼
  ┌─────────────┐     NOTICE / source obligations / UI credits; exception log with expiry
  │ Distribution  │──── Not legal advice → escalate major risks to legal
  └─────────────┘

When scanner-declared SPDX IDs conflict with package metadata, use traceable evidence (official LICENSE file, SPDX document) as the source of truth, and retain NOASSERTION or a note in SBOM until resolved.

License compatibility matrix

Common license usage constraints across different distribution scenarios (not legal advice—escalate major decisions to legal):

License Commercial closed-source use Static linking distribution SaaS (no binary distribution) Key requirements
MIT Retain copyright notice and license text
Apache-2.0 Include NOTICE file; patent grant (bilateral)
LGPL-2.1 ⚠️ ⚠️ Dynamic link or provide object files Closed-source apps may dynamically link; modifications to LGPL library itself must be open-sourced
GPL-3.0 ❌ Requires legal review ❌ Requires entire program to be GPL ⚠️ AGPL-3.0 stricter (network service also triggers) Copyleft infects; distribution requires all source code to be open
  • NOASSERTION: use as SBOM field placeholder when metadata is missing and not yet manually confirmed.
  • Scanner-output UNKNOWN must enter a review queue; must not be silently mapped to allowed.

License fields in SBOMs and review

CycloneDX licenses and SPDX JSON licenseDeclared / licenseConcluded should share provenance with CI scans and the lockfile; on merge, diff the previous SBOM’s license set.

Suggested automation

  • Ship SPDX or CycloneDX with each release artifact, bound to image / artifact digest.
  • Label or block merges on license changes (per org policy).
  • Import SBOMs into vuln + license dashboards; unify UNKNOWN tickets.

Human / agent checks

  • Under dual license, chosen terms match actual distribution.
  • Transitive upgrades introducing copyleft are within the allow table.
  • Exception records, re-review dates, and owners.

Allowlists, distribution shape, and NOTICE

Static vs dynamic linking, containers, and pure SaaS change “source offer—and “copyright notice—duties; the SKILL should list files that ship (LICENSE, NOTICE, third-party list) per delivery shape.

Version the org allow table and align it with pipeline gates; exceptions need ticket, approver, and re-review date. Generate “About / open source—pages from the SBOM or build-time credits—avoid hand-copy drift.

SPDX JSON package fragment lab

Fill coordinates and an SPDX license expression to produce a single packages[] element for SPDX 2.3 JSON (you still need document root SPDXID, relationships, etc.).

Optional fields

Illustrative only; a full SBOM also needs spdxVersion, dataLicense, document SPDXID, relationships, etc. CycloneDX users map licenses to components[].licenses.

---
name: license-compliance
description: Scan open-source licenses, generate NOTICE file, CI blocking for disallowed licenses, SBOM integration
---
# Steps
1. Run license-checker or FOSSA CLI: generate license-report.json
2. CI blocking: GitHub Actions deny GPL; block merge on policy violation
3. SPDX License Expression: parse AND/OR compound expressions, flag UNKNOWN for review
4. Compatibility matrix: check MIT/Apache/LGPL/GPL against distribution model (binary/SaaS)
5. NOTICE file: auto-generate from license-checker --customFormat; ship with release artifacts
6. SBOM integration: licenseDeclared / licenseConcluded field validation per component
7. Version diff: compare license field changes between SBOM versions; trigger review on new copyleft
8. Org allowlist: version-controlled; exceptions with ticket, approver, and re-review date
9. UNKNOWN handling: must enter review queue; do not silently map to allowed
10. Dual licensing: confirm which license applies to the actual use and distribution model
11. Static vs dynamic vs SaaS: LGPL static linking requires object files; GPL SaaS triggers AGPL
12. UI open-source notices page: generated from SBOM or build-time attribution file; avoid manual drift

# Anti-patterns
- Do NOT map UNKNOWN licenses to allowed without manual verification
- Do NOT use GPL libraries in commercial closed-source products without legal review
- Do NOT maintain open-source attribution page manually (sync with SBOM/build outputs)

Back to skills More skills