
Zero-dependency CLI scanner for npm/PyPI supply chain compromises. Detects compromised packages in lockfiles and system-level IOCs from attacks like Mini Shai-Hulud (CVE-2026-45321).
Zero-dependency CLI scanner for npm and PyPI supply chain compromises.
On May 11, 2026, a self-propagating supply chain worm dubbed Mini Shai-Hulud (CVE-2026-45321, GHSA-g7cv-rxg3-hmpx) compromised the npm ecosystem. Attributed to TeamPCP (aka DeadCatx3, PCPcat, ShellForce, CipherForce), the malware hijacked GitHub Actions OIDC tokens to publish malicious packages with valid SLSA Build Level 3 provenance. It stole credentials from CI/CD pipelines, cloud providers, and cryptocurrency wallets, and installed persistence hooks in Claude Code and VS Code. A built-in dead-man switch threatened to wipe the user's home directory if npm tokens were revoked.
Affected packages included TanStack router and start packages, Mistral AI SDKs, OpenSearch client, UiPath tooling, and dozens of others. Because supply chain attacks move fast, organizations need a lightweight, trustworthy scanner they can run anywhere without adding new dependencies to their own attack surface.
package-lock.json, pnpm-lock.yaml, yarn.lock, bun.lock, bun.lockb, poetry.lock, Pipfile.lock, and requirements.txtfs, path, child_process, os). The scanner does not increase your supply chain risk0 = clean, 1 = findings, 2 = error)src/db.ts; update the file and rerunNo installation required. Run directly with your package runner of choice:
# npx
npx @digi4care/shai-scan
# bunx
bunx @digi4care/shai-scan
# pnpm dlx
pnpm dlx @digi4care/shai-scan
Global install (optional):
npm install -g @digi4care/shai-scan
# or
pnpm add -g @digi4care/shai-scan
From source:
git clone https://github.com/digi4care/shai-scan.git
cd shai-scan
pnpm install
bun run src/cli.ts --help # Bun (recommended for development)
# or build and run with Node.js:
pnpm run build && node dist/cli.js --help
npx @digi4care/shai-scan
npx @digi4care/shai-scan ~/projects/my-app
npx @digi4care/shai-scan --json .
npx @digi4care/shai-scan --sarif --sarif-file results.sarif .
#!/bin/bash
npx @digi4care/shai-scan --severity high . || {
code=$?
if [ "$code" -eq 1 ]; then
echo "Supply chain findings detected"
exit 1
elif [ "$code" -eq 2 ]; then
echo "Scanner error"
exit 2
fi
}
name: Supply Chain Scan
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: pnpm install --frozen-lockfile
- run: npx @digi4care/shai-scan --severity high .
name: Supply Chain Scan SARIF
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 6 * * 1'
jobs:
scan:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: pnpm install --frozen-lockfile
- run: npx @digi4care/shai-scan --sarif --sarif-file results.sarif .
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
| Format | Flag | Description |
|---|---|---|
| Text | (default) | Human-readable table of findings with severity, package name, version, and campaign details |
| JSON | --json | Structured JSON array of findings, suitable for ingestion into SIEMs or custom dashboards |
| SARIF | --sarif | OASIS SARIF 2.1.0 format for upload to GitHub Code Scanning, GitLab Secure, or other SARIF consumers |
Example JSON excerpt:
[
{
"package": "@tanstack/react-router",
"version": "1.169.5",
"ecosystem": "npm",
"severity": "critical",
"campaign": "mini-shai-hulud-wave4",
"cve": "CVE-2026-45321",
"reference": "https://github.com/TanStack/router/security/advisories/GHSA-g7cv-rxg3-hmpx"
}
]
| Code | Meaning |
|---|---|
| 0 | No compromised packages or IOCs detected |
| 1 | One or more findings detected |
| 2 | Runtime error (invalid path, unreadable lockfile, etc.) |
When a new supply chain attack is discovered, update src/db.ts:
CompromisedVersion[] array with the affected packages and versionsCampaign object to the CAMPAIGNS array, including CVE/GHSA identifiers, severity, description, reference URLs, and IOC indicatorsbuildLookup() function automatically rebuilds the lookup map on the next runNo rebuild step is required when using Bun. Changes to src/db.ts take effect immediately with bun run src/cli.ts. For the npm package, run pnpm run build after editing.
Zero runtime dependencies: The scanner uses only Node.js/Bun built-in modules. It does not download or execute third-party code at runtime, eliminating the risk that the scanner itself becomes a compromise vector.
pnpm as package manager: pnpm uses strict lockfiles, does not execute lifecycle scripts by default, and supports content-addressable storage. These properties reduce the attack surface compared to other package managers.
Recommended .npmrc settings: For maximum protection when installing packages, add the following to your project or global .npmrc:
ignore-scripts=true
engine-strict=true
No network calls: shai-scan does not phone home, download signatures, or require an API key. All campaign data is shipped with the package.
The following packages and versions are known to be compromised in CVE-2026-45321 (Mini Shai-Hulud Wave 4). This is a representative subset; the full list is maintained in src/db.ts.