pip-licenses Integration with DefectDojo
pip-licenses Integration with DefectDojo
pip-licenses is an open source command-line tool, maintained on GitHub by raimon49, that lists the Python distributions installed in an environment along with the license each one declares. It reads package metadata from the active Python environment and can print the result as a table, Markdown, CSV, JSON, and other formats. The JSON output, with name, version, and license per package, is what DefectDojo imports.
pip-licenses Integration with DefectDojo
Our legal team asked a simple question before a product release: which licenses ship in the Python services? pip-licenses answered it in seconds, but the answer lived in a terminal window and was out of date by the next dependency bump. Importing pip-licenses reports into DefectDojo keeps that license inventory on each Asset, updates it on every build, and flags the packages whose license nobody could determine, so they get reviewed before release.
Why pip-licenses Matters
License risk is a supply chain problem that vulnerability scanners do not address. A package with no security issues can still carry license terms that conflict with how the software is distributed.
- It reports what is actually installed in the environment, including transitive dependencies, not just what a requirements file lists.
- It is lightweight and runs anywhere Python runs, which makes it easy to add to an existing build.
- It surfaces packages with missing license metadata, which are the ones most likely to need manual review.
- It shows the license string each package declares, so reviewers start from the package's own claim rather than a guess from its name.
- On its own, it judges nothing. It is an inventory, and policy decisions need a place to be recorded and tracked.
Advantages of This Integration
What we gained by importing pip-licenses output into DefectDojo:
- A license inventory per Asset. Every installed package becomes an informational Finding on the Asset, with component name, version, and license, so the inventory is searchable and reportable.
- Unknown licenses stand out. Packages whose license is
UNKNOWNor missing are raised to Low, so they can be filtered, assigned, and tracked to a decision. - Change tracking across builds. Deduplication uses component name, component version, and the license string. Reimporting after a dependency upgrade mitigates the old version's entry and adds the new one, and a license change on the same version shows up as a new Finding.
- Documented decisions. A package with an unusual license can be risk-accepted with a note and an expiration date, which leaves an audit trail for legal review.
- Next to vulnerability data. License entries sit on the same Asset as SCA vulnerability findings for the same packages, which gives reviewers both views in one place.
How This Integration Works
DefectDojo imports pip-licenses output with the pip-licenses Scan scan type, which expects the JSON array written by --format=json.
1. Generate the report inside the project's environment. pip-licenses reports on the environment it runs in, so activate the project's virtual environment (or run it in the same container image) first:
pip-licenses --format=json --with-authors --with-urls > pip-licenses.json
The --with-authors and --with-urls options add the package author and project URL, which the parser includes in each Finding's description. A plain pip-licenses --format=json also works.
2. Import the file. In the UI, open the Engagement, choose Import Scan Results, select pip-licenses Scan, and upload the file. Through the API, available in Community Edition and DefectDojo Pro:
curl "https://YOUR_INSTANCE/api/v2/import-scan/"
-H "Authorization: Token $DD_API_TOKEN"
-F "scan_type=pip-licenses Scan"
-F "file=@pip-licenses.json"
-F "product_name=reporting-api"
-F "engagement_name=License Review"
-F "auto_create_context=true"
DefectDojo Pro users can run the same import with Universal Importer:
universal-importer import
--defectdojo-url "https://YOUR_INSTANCE.cloud.defectdojo.com/"
--scan-type "pip-licenses Scan"
--report-path "./pip-licenses.json"
--product-name "reporting-api"
--engagement-name "License Review"
--auto-create-context
3. Reimport on dependency changes. Send each new report to /api/v2/reimport-scan/ for the same Test so removed or upgraded packages are mitigated and new ones are added.
Data Granularity: What Gets Imported
| DefectDojo Field | Source in pip-licenses JSON | Notes |
|---|---|---|
| Title | Name, Version, License |
Formatted as name version: license, or "no license declared" |
| Severity | License |
Info when a license is declared; Low when it is UNKNOWN, UNKNOWN LICENSE, NONE, or empty |
| Description | Name, Version, License, Author, URL |
Author and URL included when present; unknown licenses get a review note |
| Component Name | Name |
The Python distribution name |
| Component Version | Version |
The installed version |
| Vuln ID from Tool | License |
The license string, or UNKNOWN when missing |
| Finding type | Static | All entries are static |
| Deduplication | Hashcode | Component name, component version, vuln ID from tool |
DefectDojo does not decide which licenses are acceptable. Policy is applied by your team during triage, using the license recorded on each Finding.
Use Cases
Before a release: A product team imports pip-licenses output from the release build and filters the Asset's findings by license. Anything copyleft or unrecognized goes to legal review, and the outcome is recorded as a risk acceptance or a dependency change.
In a CI/CD pipeline: Every build of a Python service reimports its license inventory. New dependencies show up as new Findings in the Test, so a reviewer sees exactly which packages a pull request introduced.
For customer due diligence: When a customer asks for the licenses in a delivered product, the team exports the current findings for the Asset rather than rebuilding a list by hand.
Cleaning up metadata gaps: A platform team filters for Low pip-licenses findings across all Assets to find packages with no license metadata, then confirms each license from the project's source and documents it.
Operational Tips
- Run pip-licenses in the same environment you ship, such as the production container image. A developer laptop's environment usually has extra tools that are not part of the product.
- Expect one Finding per installed package. Use a dedicated Engagement or Test for license data so it does not crowd vulnerability views, and filter on the scan type in reports.
- Set
minimum_severity=Lowon import if you only want packages with undetermined licenses to appear, at the cost of losing the full inventory. - Because the license string is in the hash, a package that changes its declared license appears as a new Finding. Treat that as a prompt for review.
- License strings vary between packages (for example "BSD License" and "BSD-3-Clause"). Filter on several forms when searching for a license family.
- Pair pip-licenses with a Python vulnerability scanner on the same Asset so license and security reviews for a dependency happen together.
- Tag each import with the build or release it came from (for example
tags=release-4.2) so you can show which license inventory applied to a given shipped version.