Scan your dependencies for bus-factor risk — find the load-bearing packages maintained by one unpaid person before they become the next xz.
JavaScript
0
0 commits
updated Jul 14, 2026
Your supply chain, X-rayed. Find the load-bearing package maintained by one unpaid person, the impostor pretending to be it, and the known CVE riding along — before they become the next xz.
Your app depends on thousands of packages maintained by a few hundred people — and some of them are one burnt-out person away from collapse. Others are impostors, or are shipping code that runs the moment you npm install. busfactor finds all of them.
npx busfactor
No install. No signup. Zero dependencies — a supply-chain security tool shouldn't ship a supply chain.
busfactor scores your dependencies on two axes and keeps them distinct, so a neglected package is never confused with a hostile one:
The dangerous ones aren't just "unmaintained" — they're load-bearing and fragile. That's the xz profile.
lodahs for lodash, a Cyrillic reаct for react, cross-env.js for cross-envpreinstall/postinstall command text for real attack behavior: remote-code fetch (curl … | sh), node -e/eval, base64 decode-and-execute, raw-IP callbacks, and environment/credential exfiltration (secret source + network sink). Plus the no-repo "dropper" shape.99.99.99, 999.0.0) published to outrank an internal packageEvery threat finding is a flag, not a verdict: a package is only marked malicious-pattern when an inherently-damning signal fires (impostor name, dropper, exfil/exec install script, critical CVE) or two independent signals corroborate — the control that keeps precision high.
The headline is the intersection: a package that is load-bearing and fragile and vulnerable/impostor/malicious.
busfactor — supply-chain security report
my-app
Grade F 460 packages scanned
● 215 maintained by a single person
● 6 showing active attack patterns
● 26 with suspicious threat signals
🚨 CRITICAL EXPOSURE (load-bearing or fragile — AND actively threatened)
▸ js-yaml 1 known vulnerability (worst: moderate, CVSS up to 5.3)
⚡ Threat signals (behaving like an attack — impostor names, install scripts, known CVEs)
[malicious-pattern] evil-dropper
▪ runs an install script and has no public repository — a common dropper pattern
[suspicious] lodahs
▪ looks like popular package 'lodash' (1 edit away)
npx busfactor # scan ./ (direct deps)
npx busfactor ./my-app --all # include the full transitive tree from package-lock.json
npx busfactor --audit # threat axis only (impostors, install scripts, CVEs)
npx busfactor --card # write a shareable SVG security card
npx busfactor --json > report.json # machine-readable output
npx busfactor --all --fail-on-signal malicious-pattern # fail CI on an active attack pattern
| Flag | Description |
|---|---|
--all | Include transitive deps from package-lock.json (where the scary ones hide) |
--no-dev | Skip devDependencies |
--no-github | Skip GitHub enrichment (registry data only) |
--no-typosquat | Skip typosquat / confusable-name detection |
--no-vulns | Skip known-vulnerability (advisory) checks |
--audit | Threat-axis-only view |
--json | Machine-readable output |
--card [file] | Write a shareable SVG security card (default busfactor-card.svg) |
--fail-on <grade> | Exit code 2 if the grade is that letter or worse |
--fail-on-signal <x> | Exit code 2 on a threat level (suspicious/malicious-pattern) or a signal id (typosquat, install-script, install-script-no-repo, known-vulnerability) |
# .github/workflows/busfactor.yml
- run: npx busfactor --all --fail-on-signal malicious-pattern
Every report ends with the maintainers you can sponsor right now. The fix for the bus-factor problem isn't fear; it's funding the people holding up the ecosystem.
Enrichment passes, no setup required, all on the public registry + Node's stdlib:
GITHUB_TOKEN/GH_TOKEN or local gh login; degrades to registry-only if rate-limited rather than reporting wrong numbers.busfactor inspects registry metadata only; it never downloads or executes package code. That's a deliberate zero-dependency, safe-by-design choice — and it bounds what's detectable. Mapped loosely to the Ladisa et al. SoK taxonomy:
| ✅ Covered | ⛔ Not covered (needs tarball/runtime inspection) |
|---|---|
| Typosquat / homoglyph / separator / scope-confusion impostors | Malicious code hidden in the package body (obfuscated payloads, runtime exfil) |
| Malicious install-script command text (fetch-exec, eval, exfil) | Second-stage payloads downloaded at runtime |
| No-repo dropper shape | Sophisticated account-takeover shipping clean metadata |
| Known CVEs (version-matched) | Build/CI compromise (e.g. SolarWinds-class) |
| Dependency-confusion version tell | Manifest confusion & starjacking (need tarball-vs-registry / repo diffing) |
| Dormancy revival (corroborated) | |
| Single-maintainer / stale / unfunded / archived |
Honest limits.
popular-name + a real word, e.g. react-router) is a known class busfactor deliberately does not flag broadly — an open rule would light up half of npm and train you to mute the axis.--fail-on / --fail-on-signal.The detection heuristics and their false-positive controls are grounded in the supply-chain security literature — Ohm et al. Backstabber's Knife Collection, Zahan et al. Weak Links in the npm Supply Chain, work on low-false-positive typosquat detection, and OpenSSF Scorecard.
--fail-on grade and --fail-on-signalnode:dns, opt-in)--deep) — the one gap for runtime-hidden malwarepip / cargo / go.mod support (the engine is already ecosystem-agnostic)busfactor console) · SBOM / compliance exportMIT
JavaScript
100.0%
Scan your dependencies for bus-factor risk — find the load-bearing packages maintained by one unpaid person before they become the next xz.
JavaScript
0
0 commits
updated Jul 14, 2026
Your supply chain, X-rayed. Find the load-bearing package maintained by one unpaid person, the impostor pretending to be it, and the known CVE riding along — before they become the next xz.
Your app depends on thousands of packages maintained by a few hundred people — and some of them are one burnt-out person away from collapse. Others are impostors, or are shipping code that runs the moment you npm install. busfactor finds all of them.
npx busfactor
No install. No signup. Zero dependencies — a supply-chain security tool shouldn't ship a supply chain.
busfactor scores your dependencies on two axes and keeps them distinct, so a neglected package is never confused with a hostile one:
The dangerous ones aren't just "unmaintained" — they're load-bearing and fragile. That's the xz profile.
lodahs for lodash, a Cyrillic reаct for react, cross-env.js for cross-envpreinstall/postinstall command text for real attack behavior: remote-code fetch (curl … | sh), node -e/eval, base64 decode-and-execute, raw-IP callbacks, and environment/credential exfiltration (secret source + network sink). Plus the no-repo "dropper" shape.99.99.99, 999.0.0) published to outrank an internal packageEvery threat finding is a flag, not a verdict: a package is only marked malicious-pattern when an inherently-damning signal fires (impostor name, dropper, exfil/exec install script, critical CVE) or two independent signals corroborate — the control that keeps precision high.
The headline is the intersection: a package that is load-bearing and fragile and vulnerable/impostor/malicious.
busfactor — supply-chain security report
my-app
Grade F 460 packages scanned
● 215 maintained by a single person
● 6 showing active attack patterns
● 26 with suspicious threat signals
🚨 CRITICAL EXPOSURE (load-bearing or fragile — AND actively threatened)
▸ js-yaml 1 known vulnerability (worst: moderate, CVSS up to 5.3)
⚡ Threat signals (behaving like an attack — impostor names, install scripts, known CVEs)
[malicious-pattern] evil-dropper
▪ runs an install script and has no public repository — a common dropper pattern
[suspicious] lodahs
▪ looks like popular package 'lodash' (1 edit away)
npx busfactor # scan ./ (direct deps)
npx busfactor ./my-app --all # include the full transitive tree from package-lock.json
npx busfactor --audit # threat axis only (impostors, install scripts, CVEs)
npx busfactor --card # write a shareable SVG security card
npx busfactor --json > report.json # machine-readable output
npx busfactor --all --fail-on-signal malicious-pattern # fail CI on an active attack pattern
| Flag | Description |
|---|---|
--all | Include transitive deps from package-lock.json (where the scary ones hide) |
--no-dev | Skip devDependencies |
--no-github | Skip GitHub enrichment (registry data only) |
--no-typosquat | Skip typosquat / confusable-name detection |
--no-vulns | Skip known-vulnerability (advisory) checks |
--audit | Threat-axis-only view |
--json | Machine-readable output |
--card [file] | Write a shareable SVG security card (default busfactor-card.svg) |
--fail-on <grade> | Exit code 2 if the grade is that letter or worse |
--fail-on-signal <x> | Exit code 2 on a threat level (suspicious/malicious-pattern) or a signal id (typosquat, install-script, install-script-no-repo, known-vulnerability) |
# .github/workflows/busfactor.yml
- run: npx busfactor --all --fail-on-signal malicious-pattern
Every report ends with the maintainers you can sponsor right now. The fix for the bus-factor problem isn't fear; it's funding the people holding up the ecosystem.
Enrichment passes, no setup required, all on the public registry + Node's stdlib:
GITHUB_TOKEN/GH_TOKEN or local gh login; degrades to registry-only if rate-limited rather than reporting wrong numbers.busfactor inspects registry metadata only; it never downloads or executes package code. That's a deliberate zero-dependency, safe-by-design choice — and it bounds what's detectable. Mapped loosely to the Ladisa et al. SoK taxonomy:
| ✅ Covered | ⛔ Not covered (needs tarball/runtime inspection) |
|---|---|
| Typosquat / homoglyph / separator / scope-confusion impostors | Malicious code hidden in the package body (obfuscated payloads, runtime exfil) |
| Malicious install-script command text (fetch-exec, eval, exfil) | Second-stage payloads downloaded at runtime |
| No-repo dropper shape | Sophisticated account-takeover shipping clean metadata |
| Known CVEs (version-matched) | Build/CI compromise (e.g. SolarWinds-class) |
| Dependency-confusion version tell | Manifest confusion & starjacking (need tarball-vs-registry / repo diffing) |
| Dormancy revival (corroborated) | |
| Single-maintainer / stale / unfunded / archived |
Honest limits.
popular-name + a real word, e.g. react-router) is a known class busfactor deliberately does not flag broadly — an open rule would light up half of npm and train you to mute the axis.--fail-on / --fail-on-signal.The detection heuristics and their false-positive controls are grounded in the supply-chain security literature — Ohm et al. Backstabber's Knife Collection, Zahan et al. Weak Links in the npm Supply Chain, work on low-false-positive typosquat detection, and OpenSSF Scorecard.
--fail-on grade and --fail-on-signalnode:dns, opt-in)--deep) — the one gap for runtime-hidden malwarepip / cargo / go.mod support (the engine is already ecosystem-agnostic)busfactor console) · SBOM / compliance exportMIT
JavaScript
100.0%