Express depends on escape-html. It hasn’t been updated since 2015.
96 million weekly Express installs flow through a dependency tree containing packages that haven’t been touched in a decade — but still have active npm publish keys.
Run npx proof-of-commitment express.
Express itself scores 89/100 — consistent releases, broad maintainer team, 12+ years of history.
But Express’s direct dependencies tell a different story.
Two of them score CRITICAL:
- escape-html — score 61, 1 maintainer, 77.9M downloads/week. Last published: September 1, 2015. That’s not a typo. Version 1.0.3 is the only version this package has ever had, and it was pushed nearly 11 years ago.
- once — score 68, 1 maintainer (isaacs), 114M downloads/week. Last published: September 2016. Nearly 10 years of no changes, still pulling 114 million weekly installs.
Neither of these packages has a CVE. npm audit shows zero issues. But each one
has an npm token that can publish a new version — and there’s no mechanism in the
npm registry that prevents a compromised token from pushing 1.0.4 or 1.4.1 tomorrow.
What “no updates since 2015” actually means
The intuitive read is: it’s stable, nothing needs to change. That’s often true.
escape-html is a 20-line utility. Once you correctly escape <, >,
and &, you’re done.
But “hasn’t changed” is not the same as “can’t change.”
The npm account that published escape-html v1.0.3 in 2015 can still publish v1.0.4 today. The only thing standing between that action and 77.9 million weekly installs picking up the new version is the security of that npm token — a credential that may not have been rotated since the Obama administration.
This is the attack vector. Not a code vulnerability. Not a dependency chain. A credential that hasn’t been revoked because there was no reason to revoke it.
The axios parallel
On March 30, 2026, axios was compromised. One maintainer, 99M weekly downloads, stolen npm token. Malicious versions published. The attack lasted hours before detection. The structural conditions that enabled it were visible for years: sole maintainer, massive install base, single point of failure.
escape-html is not identical to axios. The package is genuinely small and stable. But the structural condition is the same: one person holds the publish key for a package that installs on tens of millions of machines weekly.
Our tool flagged axios as CRITICAL before the attack. escape-html scores 61 — CRITICAL. Not because it has bad code, but because it has structural fragility.
What else is in Express’s tree
Express has 27 direct dependencies. Here’s how they score:
| Package | Downloads/wk | Maintainers | Score | Risk |
|---|---|---|---|---|
escape-html | 77.9M | 1 | 61 | CRITICAL |
once | 114M | 1 | 68 | CRITICAL |
The rest of Express’s direct dependencies are reasonably well-maintained. But these two account for 192 million combined weekly downloads behind a single npm token each.
The broader picture
Express isn’t uniquely problematic. The pattern shows up everywhere we look:
- supports-color — 422M downloads/week, 1 maintainer (sindresorhus), last release 233 days ago. Pulled by virtually every CLI tool and test runner in existence.
- rimraf — 138M downloads/week, 1 maintainer, CRITICAL. The
rm -rfutility of Node.js. - @types/node — 315M downloads/week, 1 maintainer, CRITICAL. In every TypeScript project.
- chokidar — 167M downloads/week, 1 maintainer, CRITICAL. Watches your files in Vite, webpack, and nodemon.
None of these have CVEs. All of them have a sole npm token that, if compromised, would reach hundreds of millions of weekly installs within 24 hours.
What you can do
Understanding the structural risk in your dependency tree is step one. You can’t patch this the way you patch a CVE — there’s no fix to apply. What you can do:
- Know which packages in your tree are structurally fragile
- Monitor for unexpected new versions from sole-maintainer packages
- Use package version pinning in lock files (which you’re probably already doing)
- Check npm provenance when available:
npm audit signatures
Audit your dependencies now — zero install:
npx proof-of-commitment express # scores express + direct deps
npx proof-of-commitment --file package-lock.json # scores full tree Or use the browser demo at getcommit.dev/audit — paste your own packages or drop a lock file.
This scoring is behavioral, not code-scanning. It identifies structural conditions that correlate with successful supply chain attacks — it doesn’t predict which packages will be attacked or when. Some sole-maintained packages are more carefully secured than team projects. The score is a risk signal, not a verdict.