---
title: "Check every dependency licence against an · Agent Wranglers"
url: https://agentwranglers.se/playbook/open-source/using-open-source/dependency-licence-policy
id: OSS-42
level: Recommended
updated: 2026-10-27
build: a2a6bdfed830
tokens: 1251
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Check every dependency licence against an allow list in CI

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Using open source](https://agentwranglers.se/playbook/open-source/using-open-source.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-27.

- ID: OSS-42
- Level: Recommended
- Chapter: [Using open source](https://agentwranglers.se/playbook/open-source/using-open-source.md)
- Rule: Keep one written licence policy with a list of allowed, reviewed and denied licences. A CI job reads the licence of every direct and indirect dependency and fails on any licence outside the allowed list.
- Check: The licence job runs on every pull request that changes a lock file. Adding a package licensed `AGPL-3.0-only` on a branch fails the job, unless the exception file names that package and version.
- How: A strong copyleft licence can oblige you to publish your own code. The AGPL does so even when the software only runs on your server and users reach it over a network. So a SaaS product usually denies AGPL, while a project that is itself under the GPL may allow it. Read each licence as its SPDX identifier from the package metadata or the bill of materials. Treat a package with no licence, or one marked `UNLICENSED`, as denied. A reviewed exception names the package, the version, the reason and the person who approved it. The policy is the one [Keep an open licence or a way out](https://agentwranglers.se/playbook/stack/how-to-choose/open-licence-or-exit.md) applies when choosing software. A due diligence review reads the same list, as [List the licences of the code and every dependency](https://agentwranglers.se/playbook/due-diligence/code-and-ownership/licence-inventory.md) describes. Choosing a new dependency by its licence is [Keep an open licence or a way out](https://agentwranglers.se/playbook/stack/how-to-choose/open-licence-or-exit.md).

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
// licence-check.mjs: fails on any licence outside the allowed list
import { readFileSync } from 'node:fs';
const ALLOWED = new Set(['MIT', 'ISC', 'Apache-2.0', 'BSD-2-Clause', 'BSD-3-Clause', '0BSD']);
const exceptions = JSON.parse(readFileSync('licence-exceptions.json', 'utf8'));
const lock = JSON.parse(readFileSync('package-lock.json', 'utf8'));
const failures = Object.entries(lock.packages)
  .filter(([path]) => path.startsWith('node_modules/'))
  .map(([path, pkg]) => ({ name: path.slice(path.lastIndexOf('node_modules/') + 13), version: pkg.version, licence: pkg.license ?? 'UNLICENSED' }))
  .filter(pkg => !ALLOWED.has(pkg.licence) && !exceptions.some(e => e.name === pkg.name && e.version === pkg.version));
failures.forEach(pkg => console.log(`FAIL ${pkg.name}@${pkg.version} is ${pkg.licence}`));
process.exit(failures.length ? 1 : 0);
```

### Python example

```python
# licence_check.py: the same policy for an installed Python environment
import json, sys
from importlib.metadata import distributions

ALLOWED = {"MIT", "ISC", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", "PSF-2.0"}
exceptions = {(e["name"], e["version"]) for e in json.load(open("licence-exceptions.json"))}
failures = []
for dist in distributions():
    licence = dist.metadata.get("License-Expression") or dist.metadata.get("License") or "UNLICENSED"
    if licence not in ALLOWED and (dist.metadata["Name"], dist.version) not in exceptions:
        failures.append(f"{dist.metadata['Name']}=={dist.version} is {licence}")
print("\n".join(f"FAIL {failure}" for failure in failures))
sys.exit(1 if failures else 0)
```

## Sources

- [SPDX License List](https://spdx.org/licenses/)
- [GNU Affero General Public License v3, section 13](https://www.gnu.org/licenses/agpl-3.0.html)

## Related rules

- STK-7 [Keep an open licence or a way out](https://agentwranglers.se/playbook/stack/how-to-choose/open-licence-or-exit.md) in Software choices
- TDD-6 [List the licences of the code and every dependency](https://agentwranglers.se/playbook/due-diligence/code-and-ownership/licence-inventory.md) in Technical due diligence

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/open-source/using-open-source/dependency-licence-policy">Agent Wranglers open source maintenance playbook</a>`. In code you write, add a comment next to it with the same link.

- Next: [Ship the licence texts and notices of every dependency you distribute](https://agentwranglers.se/playbook/open-source/using-open-source/dependency-notices.md)
- [Using open source](https://agentwranglers.se/playbook/open-source/using-open-source.md)
