PyDependencyCheck
Dependency intelligence and supply-chain security for Python projects. A Rust core (dependency parsing, graph algorithms, OSV vulnerability scanning) wrapped in a Python CLI: scan dependencies, see who introduced them and why, find unused packages, check license compliance, generate signed SBOMs, and gate CI builds on a real health score.
What it does
- Scan: auto-detect and parse
requirements.txt,pyproject.toml(PEP 621 and Poetry), andconstraints.txt, handling every PEP 508 version operator and extras. - Why / trace: git-blame-based provenance (who added a dependency, in which commit) and full chronological history across the project's git log.
- Health: a real, computed 0-100 score combining live OSV.dev vulnerability data, PyPI release staleness, AST-detected dead dependencies, and dependency-graph complexity.
- SBOM export: CycloneDX 1.4 and SPDX 2.3 JSON, with optional RSA-SHA256 signing and verification.
- License compliance: fetches real PyPI license metadata, classifies permissive/copyleft/restricted, and checks compatibility against your project's own license.
- CI gating:
gatecomputes the same health score and exits non-zero on failure, with GitHub Actions::error/::warning/::noticeannotations when run inside a GitHub Actions job. - Drift & history: SQLite-backed snapshots so you can diff what changed since a baseline.
- OpenTelemetry: optional tracing/metrics via
--otel, defaulting to a console exporter (no collector required) or OTLP/Jaeger/Prometheus if configured.
Installation
pip install pydependencycheck
For SBOM signing (needs cryptography) or OpenTelemetry export:
pip install "pydependencycheck[sbom,otel]"
Requires Python 3.8+. Prebuilt wheels are published for Linux, macOS (Intel/Apple Silicon), and Windows; see .github/INSTALL.md if you need to build from source.
Quick start
# Scan the current project (--path defaults to ".")
pydependencycheck scan
# Why is this package installed, and who added it?
pydependencycheck why requests
# Full git history for a dependency (added/upgraded/downgraded over time)
pydependencycheck trace requests
# Real health score: live vulnerabilities, staleness, dead deps, complexity
pydependencycheck health
# License compliance report, checked against your project's license
pydependencycheck licenses --project-license MIT
# Export a signed CycloneDX SBOM
pydependencycheck export --format cyclonedx --output sbom.json
# Gate a CI build: exits non-zero if health/vulnerabilities/dead-deps fail thresholds
pydependencycheck gate --min-health 50
Commands
| Command | What it does |
|---|---|
scan |
Parse dependency files, report direct/transitive counts (table, JSON, HTML, or Markdown) |
list |
Table of all detected dependencies |
why PACKAGE |
Git-blame provenance: who added it, in which commit |
trace PACKAGE |
Current status plus full git history for that dependency |
health |
Computed health score (vulnerabilities, staleness, dead deps, complexity) |
licenses |
License classification + compatibility check per dependency |
export |
SBOM export (CycloneDX or SPDX), optionally signed |
gate |
CI gate: real exit code based on health/vulnerability/dead-dep thresholds |
remediate |
Patch vulnerable dependencies to their OSV fix_version, optionally as a real git branch/commit + GitHub PR |
snapshot |
Save or inspect a dependency snapshot |
history |
Timeline of saved snapshots |
drift |
Diff the current scan against a saved baseline |
Run pydependencycheck COMMAND --help for the full option list on any command (most support --path, and scan/export/licenses/health/gate support --offline/--path variants where relevant).
Health scoring
health (and gate) combine four real, independently-computed factors:
pydependencycheck health
Dependency Health Score: 87/100 (Excellent)
Health Score Breakdown
┏━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┓
┃ Factor ┃ Score ┃ Status ┃
┡━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━┩
│ Overall Health │ 87/100 │ ████████░░ Excellent │
│ Vulnerabilities │ 100/100 │ ██████████ Excellent │
│ Maintenance │ 100/100 │ ██████████ Excellent │
│ Quality │ 40/100 │ ████░░░░░░ Poor │
│ Complexity │ 95/100 │ █████████░ Excellent │
└─────────────────┴─────────┴──────────────────────┘
Vulnerabilities and staleness require live network calls (OSV.dev and PyPI's JSON API); pass --offline to skip them and get a deterministic score from local data only (dead-dependency detection and graph complexity).
Automated remediation
remediate turns an OSV.dev vulnerability finding into an actual patch --
not just a report:
# Dry run: prints a unified diff for every affected file, changes nothing
pydependencycheck remediate
# Write the fixed versions to requirements.txt/pyproject.toml for real
pydependencycheck remediate --apply
# Create a real git branch + commit for the fix, push it, and open a GitHub
# PR via the `gh` CLI (if installed and authenticated)
pydependencycheck remediate --pr
2 fixable vulnerable package(s):
requests: 2.25.0 -> 2.33.0 [GHSA-9hjg-9r4m-mvj7, PYSEC-2023-74, ...]
flask: 2.0.0 -> 2.3.2 [GHSA-m2qf-hxjv-5gpq]
--- requirements.txt ---
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,2 @@
-requests==2.25.0
-flask==2.0.0
+requests==2.33.0
+flask==2.3.2
Only exact == pins in requirements.txt/constraints.txt/pyproject.toml
are patched (a range like >=2.0,<3.0 doesn't name one concrete version to
bump). With --pr but no gh CLI available, the branch is still created
and pushed for real -- open the PR manually.
SBOM export and signing
# Generate keys once
python3 -c "from pydependencycheck.sbom import SBOMSigner; SBOMSigner().generate_keys('signing-key.pem')"
# Export a signed SBOM
pydependencycheck export --format cyclonedx --sign --key signing-key.pem --output sbom.json
The SBOM carries a SHA-256 integrity hash and (when --sign is used) an RSA-SHA256 signature over the document, verifiable with SBOMSigner.verify_sbom().
CI gating with GitHub Actions
name: Dependency Check
on: [push, pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- run: pip install pydependencycheck
- run: pydependencycheck scan --save-snapshot
- run: pydependencycheck gate --min-health 50
- run: pydependencycheck export --format cyclonedx --output sbom.json
- uses: actions/upload-artifact@v3
with:
name: sbom
path: sbom.json
gate prints ::error/::warning/::notice GitHub Actions annotations automatically when GITHUB_ACTIONS is set, and always sets the process exit code (1 on failure), so it works as a real CI gate on any CI system, not just GitHub Actions.
OpenTelemetry
pydependencycheck health --otel
Defaults to a console exporter backed by the real OpenTelemetry SDK (ConsoleSpanExporter/ConsoleMetricExporter) -- genuine spans and metrics printed to stdout, no collector required. Pass --otel-exporter otlp|jaeger|prometheus to ship to real infrastructure if you have it configured; if the corresponding exporter package isn't installed, it falls back to console rather than silently doing nothing.
Architecture
Rust workspace (crates/) does the heavy lifting, exposed to Python via PyO3:
pydep-parser-- PEP 508 requirements/pyproject.toml parsing (extras, markers, every version operator)pydep-graph-- dependency graph construction, cycle detection, topological sort (petgraph)pydep-ast-- import extraction and dead-dependency detectionpydep-security-- OSV.dev vulnerability queries and risk scoringpydep-py-- PyO3 bindings tying it together aspydependencycheck._pydependencycheck
The Python package (python/pydependencycheck/) is the CLI, plus SBOM generation, license analysis, git integration, SQLite-backed snapshot storage, and OpenTelemetry instrumentation.
Testing: 45 Rust unit tests (cargo test --workspace) across all four crates, plus 126 Python tests (pytest tests/) covering the CLI end-to-end, the XSS fix, SBOM signing/verification, license classification, health scoring, and the SQLite storage layer.
Requirements
Python 3.8+ on Linux (x86_64), macOS (Intel/ARM), or Windows (x86_64).
License
Proprietary License - free to use with explicit attribution. See LICENSE for details.
When using PyDependencyCheck, include this attribution:
Powered by PyDependencyCheck (https://github.com/Mullassery/PyDependencyCheck)
Known issues
setup.py/setup.cfg-only projects (norequirements.txtorpyproject.toml) are not parsed yet — AST parsing ofsetup.pyand INI parsing ofsetup.cfgare unimplemented (crates/pydep-parser/src/setup.rs,python/pydependencycheck/scanner.py), and are consequently also not covered byremediate.- The health-score "Quality" factor is a single metric today; aggregating multiple quality signals is tracked as future work (
python/pydependencycheck/scanner.py). - Fixed in this pass:
check_vulnerabilities()was passing the full PEP 508 specifier (e.g."==2.25.0") to OSV.dev instead of the bare version --Version::parse("==2.25.0")fails as invalid semver, so OSV's range matching silently fell back to exact-string matching against nothing, meaninghealth/gatereported zero vulnerabilities for essentially every exactly-pinned dependency. Also fixed:fix_versioncould come back as a raw git commit hash instead of a PyPI version when an advisory'saffected[].rangeslisted a GIT-type range before its ECOSYSTEM range (both incrates/pydep-security/src/osv.rs; seefix_version_ignores_git_range_and_uses_ecosystem_rangefor the regression test). - No open GitHub issues at the time of this writing.
Support
Release files for pydependencycheck 1.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pydependencycheck-1.4.0.tar.gz | 117.9 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| pydependencycheck-1.4.0-cp311-cp311-win_amd64.whl | CPython 3.11 | CPython 3.11 | Windows x86-64 | Details |
| pydependencycheck-1.4.0-cp311-cp311-macosx_11_0_arm64.whl | CPython 3.11 | CPython 3.11 | macOS 11.0+ ARM64 | Details |
| pydependencycheck-1.4.0-cp311-cp311-macosx_10_12_x86_64.whl | CPython 3.11 | CPython 3.11 | macOS 10.12+ x86-64 | Details |
| pydependencycheck-1.4.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.8 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| pydependencycheck-1.4.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.8 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| pydependencycheck-1.4.0-cp38-abi3-macosx_11_0_arm64.whl | CPython 3.8 | abi3 | macOS 11.0+ ARM64 | Details |
| pydependencycheck-1.4.0-cp38-abi3-macosx_10_12_x86_64.whl | CPython 3.8 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 11.9 MB
Release files / pydependencycheck-1.4.0.tar.gz
| Download URL | pydependencycheck-1.4.0.tar.gz |
|---|---|
| Size | 117.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
49452f6fad009a7939ba30ebe1d7fc126fc22efbc777c549257be5c3b5a55c33
|
|
BLAKE2b-256 checksum How to use checksums |
31a9a3fa8875fe4baa0210af94581f8d0f453622c621b0941dc84f011aa61be4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / pydependencycheck-1.4.0-cp311-cp311-win_amd64.whl
| Download URL | pydependencycheck-1.4.0-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 1.4 MB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
d26741e98473894c97c5cc21db4df0b4b3c0cc3b544b5cf8b89d5dbff7828ec3
|
|
BLAKE2b-256 checksum How to use checksums |
d538c7f3ebd9099e3cf8f3f35481c37c34215925ec016ff091bb00d14fe78727
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / pydependencycheck-1.4.0-cp311-cp311-macosx_11_0_arm64.whl
| Download URL | pydependencycheck-1.4.0-cp311-cp311-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.11 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
30bd89dd56419ba869bd8a88539f6429404ce5399b5b200614ddba93767745a3
|
|
BLAKE2b-256 checksum How to use checksums |
3d258a7974a218030fdcab36941b09470566c522b26c9ba6a8fcef45bfd2a8bd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / pydependencycheck-1.4.0-cp311-cp311-macosx_10_12_x86_64.whl
| Download URL | pydependencycheck-1.4.0-cp311-cp311-macosx_10_12_x86_64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.11 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
6c023a9d0d52a517744cda63622ea83d43946ddc87a9ec963a28ec8890ba72a9
|
|
BLAKE2b-256 checksum How to use checksums |
e6a2d3ad46428b78095a62c19a927ed07f26fb885247d3d4340aed05a4323e97
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / pydependencycheck-1.4.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | pydependencycheck-1.4.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 2.2 MB |
| Tags | CPython 3.8 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
daec9b9b90e4dbbb4c4a09a8140aca56dc8775b2b41ee694a1bf86a203c6eb8d
|
|
BLAKE2b-256 checksum How to use checksums |
cb973b04b84c3bd4503e97718e67b1a5ecaaabdb79feaa4970207376242d14ad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Release files / pydependencycheck-1.4.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | pydependencycheck-1.4.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 2.1 MB |
| Tags | CPython 3.8 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
147a787ffc7dc17c5393242b32f4a2ca9f17564b5300bbfb33ca9e3b3237955b
|
|
BLAKE2b-256 checksum How to use checksums |
60c18b50a81415402400e0f41125384a4c4ab3a007135ac082bd5c0cd858de5e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Release files / pydependencycheck-1.4.0-cp38-abi3-macosx_11_0_arm64.whl
| Download URL | pydependencycheck-1.4.0-cp38-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.8 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
1b432ccb5ab277871c9bf5d26de8e0cff758714d900d660a6b20840eed69a350
|
|
BLAKE2b-256 checksum How to use checksums |
98cd2ccad3dd4027d8a52b14f1e5129c5177c2d4e76d55de15925610af9054da
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Release files / pydependencycheck-1.4.0-cp38-abi3-macosx_10_12_x86_64.whl
| Download URL | pydependencycheck-1.4.0-cp38-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.8 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
d0cfd762d3079283763626f64ca3338496b40a8750e3d0ff14a89b46b22e8437
|
|
BLAKE2b-256 checksum How to use checksums |
43aaa3e0a0c78a0aa7fd0b01d832cd648d944194e2f8eb52d9d0086ab57cf334
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|