A supply chain security CLI that collects SBOMs from GitHub repositories and searches them for compromised, malicious, or vulnerable package versions.
- Python 3.11+
- GitHub CLI installed and authenticated (
gh auth login) - Dependency graph enabled on target repos (Settings → Security & analysis → Dependency graph)
Collect SBOMs for specific repos or an entire org:
python chainwatch.py --org my-org --repos repo1 repo2
python chainwatch.py --org my-org --repos allHunt for a compromised package inline or from a watchlist file:
python chainwatch.py --org my-org --repos all --search lodash@4.17.21
python chainwatch.py --org my-org --repos all --search "pkg:npm/lodash@4.17.21"
python chainwatch.py --org my-org --repos all --search-file watchlist.txtFilter by ecosystem to reduce noise:
python chainwatch.py --org my-org --repos all --keep npm pypi
python chainwatch.py --org my-org --repos all --exclude npmOne term per line — either name@version or a full PURL. Blank lines and # comments are ignored:
# CVE-2024-XXXXX — short form
malicious-pkg@3.1.4
# full PURL form
pkg:npm/lodash@4.17.21
pkg:pypi/requests@2.28.0
| Flag | Short | Default | Description |
|---|---|---|---|
--org |
-o |
required | GitHub organisation name |
--repos |
-r |
required | Repo names, or all |
--output-dir |
-d |
./sboms |
Output directory |
--delay |
15s |
Delay between API calls (applied when > 5 repos) | |
--keep |
— | Keep only packages from these ecosystems (npm, pypi) |
|
--exclude |
— | Exclude packages from these ecosystems | |
--search |
-s |
— | One or more name@version or PURL terms to search |
--search-file |
-S |
— | Path to a watchlist .txt file (name@version or PURL, one per line) |
--keep and --exclude are mutually exclusive. --search and --search-file can be combined; duplicates are removed automatically.
Each repo produces a <repo>_sbom.json (or <repo>_sbom_filtered.json when filtering):
{
"repo_name": "finance-ai",
"packages": [
"pkg:npm/lodash@4.17.21",
"pkg:pypi/requests@2.28.0"
]
}A _summary.json audit log is always written, including search hits per term:
{
"org": "my-org",
"timestamp": "2024-07-15T10:32:01+00:00",
"search": {
"terms": ["requests@2.28.0"],
"hits": { "requests@2.28.0": ["finance-ai", "data-pipeline"] }
},
"succeeded": ["finance-ai", "data-pipeline"],
"failed": ["legacy-monolith"]
}# 1. Add compromised versions to a watchlist
echo "malicious-pkg@3.1.4" >> watchlist.txt
# 2. Scan the org
python chainwatch.py --org my-org --repos all \
--search-file watchlist.txt \
--output-dir ./incident-2024-07-15
# 3. Review — affected repos are listed per term in stdout and _summary.json- Search is a plain substring match on raw SBOM JSON — intentional, to ensure exact version precision.
- Only dependencies detected by GitHub's dependency graph are visible. Vendored code and non-standard manifests may not appear.
- Repos with the dependency graph disabled are skipped and recorded in
failed.