Scan every JavaScript/TypeScript repository in a GitHub organization using the
GitHub Dependency Graph SBOM API, save each repo’s SBOM to disk, and produce a
CSV report of suspicious packages (exact name@version and name-only matches).
Note: This script will also detect the Shai-Hulud worm, a recent npm malware that spreads through dependencies.
- Enumerates all repos in the org and filters to JS/TS repos automatically.
- Fetches each repository’s SPDX SBOM via the GitHub API.
- Saves the raw SBOMs under
sboms/<org>/<repo>/sbom.json. - Looks for packages listed in the built-in suspicious list and records:
- repo, package, version, relationship (e.g.,
DEPENDS_ON), SPDX id, match type
- repo, package, version, relationship (e.g.,
- Writes a consolidated CSV report:
org_sbom_hits.csv.
Why SBOM instead of
package.jsononly?
SBOM includes direct + transitive dependencies, providing a complete view of exposure.
- Dependabot enabled for all repositories via the Advanced Security control panel.
In your GitHub organization, go to Settings → Code security and analysis and ensure:- Dependency graph is enabled (org-level and repo-level).
- Dependabot alerts are enabled for all repositories.
- (Recommended) Dependabot security updates are enabled so security PRs are auto-raised.
The suspicious packages and versions used in this script were collected from the Mend blog post on the npm supply chain attack:
👉 Mend.io — NPM Supply Chain Attack: Packages Compromised by Self-Spreading Malware
The suspicious package list is now loaded from a text file (default: suspicious.txt) instead of being hardcoded.
- You can update this file with new
package@versionentries as needed. - The list has been recently updated with expanded coverage from multiple sources (Mend, JFrog, Socket.dev, etc.).
- Lines starting with
#are comments and will be ignored.
- Python 3.8+
- A GitHub Personal Access Token (PAT) with:
- Classic PAT:
reposcope is sufficient for private repos. - Fine-grained PAT: Repository permissions → Contents: Read, Dependency graph: Read.
- Classic PAT:
requestsPython package
pip install -U requestsClone or copy the script into your workspace:
npm-package-check/
├─ scan_org_sboms.py
├─ README.md
└─ (generated) sboms/
You can pass arguments or use environment variables.
python3 scan_org_sboms.py <ORG> <GITHUB_TOKEN>Example:
python3 scan_org_sboms.py org_name ghp_yourPAT123...export ORG=org_name
export GITHUB_TOKEN=ghp_yourPAT123...
python3 scan_org_sboms.py- SBOM files:
sboms/<org>/<repo>/sbom.json - CSV report:
org_sbom_hits.csv
- Store PATs in env vars or a secret manager.
- Don’t commit
sboms/or reports to public repos without sanitizing.