Yamparala-Venkata-Gopi/busfactor

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

See the code

README

busfactor

CI npm zero dependencies license

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.


What it does

busfactor scores your dependencies on two axes and keeps them distinct, so a neglected package is never confused with a hostile one:

🧍 Axis 1 — bus-factor (who could get compromised)

  • Single maintainer — how many people can get hit by a bus before this package is abandoned?
  • Staleness — no release / no commits in 2+ years, or formally deprecated
  • Load-bearing — millions of downloads a month riding on one of the above
  • Unfunded — a critical, single-maintainer package nobody is paying

The dangerous ones aren't just "unmaintained" — they're load-bearing and fragile. That's the xz profile.

⚡ Axis 2 — threat (who is behaving like an attack right now)

  • Typosquats & confusable nameslodahs for lodash, a Cyrillic reаct for react, cross-env.js for cross-env
  • Malicious install scripts — reads the preinstall/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.
  • Known vulnerabilities — live CVE/CVSS data from npm's advisory database, matched against your installed versions
  • Dependency confusion — implausibly high versions (99.99.99, 999.0.0) published to outrank an internal package
  • Dormancy revival — a long-dormant package suddenly shipping a fresh release (the xz / event-stream cadence); corroborating-only, never a lone flag
  • Attack-shaped metadata — brand-new packages with sudden high reach

Every 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)

Usage

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
FlagDescription
--allInclude transitive deps from package-lock.json (where the scary ones hide)
--no-devSkip devDependencies
--no-githubSkip GitHub enrichment (registry data only)
--no-typosquatSkip typosquat / confusable-name detection
--no-vulnsSkip known-vulnerability (advisory) checks
--auditThreat-axis-only view
--jsonMachine-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)

Use it in CI

# .github/workflows/busfactor.yml
- run: npx busfactor --all --fail-on-signal malicious-pattern

Don't just scan — fund

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.

How it works (and its honest limits)

Enrichment passes, no setup required, all on the public registry + Node's stdlib:

  1. npm registry — publish access, last release, deprecation, funding, repository, install scripts, package age.
  2. npm advisory database — known vulnerabilities (GHSA id, severity, CVSS), matched to your installed versions so already-fixed CVEs aren't reported.
  3. GitHub (optional) — real contributor counts (the true bus factor), last-commit recency, archived status. Uses your GITHUB_TOKEN/GH_TOKEN or local gh login; degrades to registry-only if rate-limited rather than reporting wrong numbers.
  4. Offline detectors — typosquat/confusable-name matching runs with no network at all.

Coverage — what it catches, and what it can't

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 impostorsMalicious 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 shapeSophisticated account-takeover shipping clean metadata
Known CVEs (version-matched)Build/CI compromise (e.g. SolarWinds-class)
Dependency-confusion version tellManifest confusion & starjacking (need tarball-vs-registry / repo diffing)
Dormancy revival (corroborated)
Single-maintainer / stale / unfunded / archived

Honest limits.

  • Install-script signals are spoofable and shape-limited. ~22% of install-time malware is indistinguishable from a legit build script by shape alone; a flag is a prompt to look, not a conviction.
  • Combosquatting (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.
  • Provenance (npm attestations) is used only to reduce false positives; its absence is never treated as a risk (most packages lack it).
  • Contributor count is a proxy for bus factor, not a measure of who can publish; both signals are shown so you can judge.
  • Default runs are non-blocking (exit 0) by design — opt into CI enforcement with --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.

Roadmap

  • Two-axis scoring: bus-factor and threat detection
  • Typosquat / confusable-name detection (offline)
  • Install-script command-text analysis (fetch-exec, eval, base64, exfil)
  • Dependency-confusion version tell + dormancy-revival (corroborated)
  • Known-vulnerability enrichment (CVE/CVSS, version-matched)
  • Corroboration invariant + provenance-based false-positive suppression
  • CI gates: --fail-on grade and --fail-on-signal
  • Relational suppression — maintainer/repo overlap between a lookalike and its target (the highest-leverage FP control in the literature)
  • Relative-popularity gate — target/candidate download ratio, to safely widen typosquat coverage
  • Ownership-change / new-publisher detection (the precise xz signal; pairs with dormancy)
  • Expired maintainer-domain takeover check (node:dns, opt-in)
  • Opt-in tarball content scanning (--deep) — the one gap for runtime-hidden malware
  • SARIF export + GitHub Action (findings in the Security tab)
  • pip / cargo / go.mod support (the engine is already ecosystem-agnostic)
  • Interactive console (busfactor console) · SBOM / compliance export

License

MIT

Yamparala-Venkata-Gopi/busfactor

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

See the code

README

busfactor

CI npm zero dependencies license

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.


What it does

busfactor scores your dependencies on two axes and keeps them distinct, so a neglected package is never confused with a hostile one:

🧍 Axis 1 — bus-factor (who could get compromised)

  • Single maintainer — how many people can get hit by a bus before this package is abandoned?
  • Staleness — no release / no commits in 2+ years, or formally deprecated
  • Load-bearing — millions of downloads a month riding on one of the above
  • Unfunded — a critical, single-maintainer package nobody is paying

The dangerous ones aren't just "unmaintained" — they're load-bearing and fragile. That's the xz profile.

⚡ Axis 2 — threat (who is behaving like an attack right now)

  • Typosquats & confusable nameslodahs for lodash, a Cyrillic reаct for react, cross-env.js for cross-env
  • Malicious install scripts — reads the preinstall/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.
  • Known vulnerabilities — live CVE/CVSS data from npm's advisory database, matched against your installed versions
  • Dependency confusion — implausibly high versions (99.99.99, 999.0.0) published to outrank an internal package
  • Dormancy revival — a long-dormant package suddenly shipping a fresh release (the xz / event-stream cadence); corroborating-only, never a lone flag
  • Attack-shaped metadata — brand-new packages with sudden high reach

Every 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)

Usage

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
FlagDescription
--allInclude transitive deps from package-lock.json (where the scary ones hide)
--no-devSkip devDependencies
--no-githubSkip GitHub enrichment (registry data only)
--no-typosquatSkip typosquat / confusable-name detection
--no-vulnsSkip known-vulnerability (advisory) checks
--auditThreat-axis-only view
--jsonMachine-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)

Use it in CI

# .github/workflows/busfactor.yml
- run: npx busfactor --all --fail-on-signal malicious-pattern

Don't just scan — fund

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.

How it works (and its honest limits)

Enrichment passes, no setup required, all on the public registry + Node's stdlib:

  1. npm registry — publish access, last release, deprecation, funding, repository, install scripts, package age.
  2. npm advisory database — known vulnerabilities (GHSA id, severity, CVSS), matched to your installed versions so already-fixed CVEs aren't reported.
  3. GitHub (optional) — real contributor counts (the true bus factor), last-commit recency, archived status. Uses your GITHUB_TOKEN/GH_TOKEN or local gh login; degrades to registry-only if rate-limited rather than reporting wrong numbers.
  4. Offline detectors — typosquat/confusable-name matching runs with no network at all.

Coverage — what it catches, and what it can't

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 impostorsMalicious 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 shapeSophisticated account-takeover shipping clean metadata
Known CVEs (version-matched)Build/CI compromise (e.g. SolarWinds-class)
Dependency-confusion version tellManifest confusion & starjacking (need tarball-vs-registry / repo diffing)
Dormancy revival (corroborated)
Single-maintainer / stale / unfunded / archived

Honest limits.

  • Install-script signals are spoofable and shape-limited. ~22% of install-time malware is indistinguishable from a legit build script by shape alone; a flag is a prompt to look, not a conviction.
  • Combosquatting (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.
  • Provenance (npm attestations) is used only to reduce false positives; its absence is never treated as a risk (most packages lack it).
  • Contributor count is a proxy for bus factor, not a measure of who can publish; both signals are shown so you can judge.
  • Default runs are non-blocking (exit 0) by design — opt into CI enforcement with --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.

Roadmap

  • Two-axis scoring: bus-factor and threat detection
  • Typosquat / confusable-name detection (offline)
  • Install-script command-text analysis (fetch-exec, eval, base64, exfil)
  • Dependency-confusion version tell + dormancy-revival (corroborated)
  • Known-vulnerability enrichment (CVE/CVSS, version-matched)
  • Corroboration invariant + provenance-based false-positive suppression
  • CI gates: --fail-on grade and --fail-on-signal
  • Relational suppression — maintainer/repo overlap between a lookalike and its target (the highest-leverage FP control in the literature)
  • Relative-popularity gate — target/candidate download ratio, to safely widen typosquat coverage
  • Ownership-change / new-publisher detection (the precise xz signal; pairs with dormancy)
  • Expired maintainer-domain takeover check (node:dns, opt-in)
  • Opt-in tarball content scanning (--deep) — the one gap for runtime-hidden malware
  • SARIF export + GitHub Action (findings in the Security tab)
  • pip / cargo / go.mod support (the engine is already ecosystem-agnostic)
  • Interactive console (busfactor console) · SBOM / compliance export

License

MIT

Languages

JavaScript

100.0%