deniz.in

Markets

Weather

Loading weather

· via dev.to (home feed)

Scan of 433 most-starred JavaScript repos finds one maintainer's packages in 99% of them

A dev.to scan of 433 popular JavaScript repositories found that half of installed npm packages have exactly one publish account, and packages from one maintainer appear in 99% of projects.

Scan of 433 most-starred JavaScript repos finds one maintainer's packages in 99% of them

A scan of the 433 most-starred JavaScript and TypeScript repositories on GitHub has put concrete numbers on a concern the xz backdoor made famous: popular open-source projects lean on a remarkably small group of publishers. According to a dev.to post by Ahmed Benhamadi, packages that the npm account sindresorhus publishes alone — 513 of them in the scan — show up in 430 of the 433 repositories, or 99%.

How the scan was built

Benhamadi wrote a small CLI, npx @genamed/busfactor, that reads a project's lockfile and reports, for each installed package, who holds the right to publish the next version, whether the package is deprecated or archived, when it was last released, and whether it declares a funding link. It then aggregates the results to show which individual accounts carry the most packages single-handedly.

For the scan itself, he started from the 600 most-starred JavaScript and TypeScript repos on GitHub and kept the 433 that have a lockfile at their root — package-lock., pnpm-lock.yaml, yarn.lock or npm-shrinkwrap.. That set resolved to 27,184 unique npm packages, cross-referenced against the npm registry and ecosyste.ms.

What the numbers show

The median project in the set installs 945 packages, and about half of those packages have exactly one account able to publish a new version. Packages whose sole publisher is an organisation, or the @types scope, were excluded from that count.

The concentration at the top is stark. After sindresorhus (99% of repos, 513 packages alone, including supports-color, camelcase and wrap-ansi) come isaacs (98%, 76 packages), juliangruber (95%, 21), ljharb (94%, 152, including resolve and deep-equal) and kevva (93%, 31). Between them, the top five appear in every single repository scanned — React, VS Code, Vue and n8n included. Further down, accounts like qix, satazor, vitaly, lukeed and esp each reach roughly 90% of the projects.

One entry stands out: nopersonsmodules, present in 88% of projects with 59 packages such as text-table, wordwrap and commondir. According to the post, this is the account packages fall into when their original author leaves the npm registry, and nothing is ever published from it. If one of those packages needs a security patch, there is effectively no one to ask.

The scan also counted dead weight: 98% of the repositories ship at least one deprecated or archived dependency. path-is-absolute and inflight — deprecated because it leaks memory — each appear in about 305 of the 433 repos, while archived packages like prop-types, regenerator-runtime, xtend and through remain widespread. Only 24% of the packages carry a funding link, although most of the busiest publishers do list a GitHub Sponsors page.

The caveats the author flags

Benhamadi is careful about what the data means. A publish account is not an active maintainer: one shared login can hide a whole team, and several accounts can represent one person plus collaborators who left years ago. Dormant also does not mean broken — many of these packages are tiny and effectively finished. The narrower question the tool answers is who would have to type the fix if one were needed tomorrow. Since everything is derived from public registry data, freshness depends on the npm registry and ecosyste.ms.

The tool and the dataset

The CLI requires Node 20, has zero runtime dependencies and caches results for a week. Flags include --md for a card to paste into a README or pull request, --svg for a shareable image, and --fail-on dead to turn it into a CI gate that fails builds containing dead dependencies.

The second half of the project is a dataset, successors., mapping abandoned packages to maintained replacements, with one sourced entry per package and weekly CI validation against the registries so a successor that itself dies gets flagged. For npm it defers to the existing e18e/module-replacements project and instead focuses on PyPI, Cargo, Go and Packagist, where no structured equivalent existed. The repository, GenAmed/busfactor on GitHub, is MIT-licensed — and, as its author notes, has a bus factor of one itself, with a GOVERNANCE.md describing what happens if he goes silent.

Why it matters

The xz backdoor demonstrated that a single overstretched maintainer can be a single point of failure for critical software. This scan suggests the situation in the JavaScript ecosystem is structural rather than exceptional: five accounts' packages reach every popular repo in the sample, and an unattended publisher account sits in almost nine out of ten projects. For engineering teams, running the tool against their own lockfiles is a cheap supply-chain audit and, with the CI flag, a way to keep dead dependencies out of merges. For the ecosystem at large, it is a nudge toward funding the people and governance arrangements that keep those 945-package installs patchable.

  • #javascript
  • #npm
  • #open-source
  • #supply-chain-security
  • #developer-tools

Related posts