A comparison of process security scores vs behavioral risk signals on npm's most critical packages.
OpenSSF Scorecard measures whether a project follows secure development practices. Code review enforcement. Branch protection. SLSA provenance. Dangerous workflow detection. It's a process security score: does this repo handle its own development securely?
I've been building getcommit.dev, which measures something different: behavioral commitment signals. Publisher depth. Download concentration. Release consistency. Whether a single npm account holds publish access for a package downloaded 400 million times per week.
This week I added Scorecard integration to the API. Each package audit now returns both scores. The comparison is worth seeing.
The seven CRITICAL packages
These are npm packages that score CRITICAL on behavioral signals: one npm publisher + more than 10 million weekly downloads. That's the exact structural profile of ua-parser-js before the October 2021 compromise, and LiteLLM before the March 2026 attack.
Package | Behavioral | Scorecard | Downloads/wk | npm publishers
-----------|------------|-----------|--------------|----------------
chalk | 🔴 CRITICAL | 3.6/10 | 413M | 1
minimatch | 🔴 CRITICAL | 6.2/10 | 562M | 1
glob | 🔴 CRITICAL | 5.5/10 | 333M | 1
lodash | 🔴 CRITICAL | 6.9/10 | 146M | 1
zod | 🔴 CRITICAL | 4.9/10 | 162M | 1
axios | 🔴 CRITICAL | 8.1/10 | 99M | 1
hono | 🔴 CRITICAL | N/A | 35M | 1
npm audit shows zero vulnerabilities on all of them.
Two tools. Two attack surfaces.
The tempting conclusion is that one tool is "better" than the other. That misses the point.
Scorecard answers: Can an attacker compromise this project's development pipeline? Weak branch protection, no code review, dangerous workflows — these are exploitable process gaps. A supply chain attack could inject malicious code via a compromised PR or CI job.
Behavioral signals answer: Can an attacker take over this package by compromising one account? When a single npm account holds publish access for a package downloaded 562 million times per week, that credential is a high-value target. Phishing it, stealing it, or finding it in a leaked secrets file is a fundamentally different attack vector than exploiting the CI pipeline.
chalk: bad on both dimensions
chalk scores 3.6/10 on Scorecard. It has one npm publisher. 413 million weekly downloads per week.
From a process security standpoint: limited code review enforcement, no SLSA provenance, weak branch protection signals. From a behavioral standpoint: a single compromised npm credential unlocks a package running in virtually every JavaScript project in production.
npm audit shows zero issues.
axios: attacked despite a strong Scorecard
axios scores 8.1/10 on Scorecard. It has strong code review, maintained CI, good token permissions. And it was attacked on March 30, 2026.
How? Stolen npm credentials. The Scorecard-measured process security was intact. The attack didn't go through the CI pipeline — it bypassed it by publishing directly to npm with a stolen publisher key.
Behavioral signals flagged axios as CRITICAL before the attack. Not because the CI was weak. Because one account held the npm publish key for a package with 99 million weekly downloads. That's the attack surface.
zod: high behavioral risk, mediocre process security
zod has 30+ GitHub contributors and a healthy development process. But it scores 4.9/10 on Scorecard — meaning there are real gaps in how development is secured. And it has one npm publisher for 162 million weekly downloads.
Stars and contributor count pointed up. Both security scores pointed to risk. npm audit showed nothing.
What this means practically
These scores don't compete. Use them together.
A package with high behavioral risk (sole publisher, massive downloads) and low Scorecard (weak code review, no branch protection) is doubly exposed: both the credential attack surface and the process exploitation surface are open.
A package with high behavioral risk but strong Scorecard still carries the credential risk — as the axios attack demonstrated.
npm audit shows you neither.
The combined scores are live in the getcommit.dev API:
curl https://poc-backend.amdal-dev.workers.dev/api/audit \
-X POST -H "Content-Type: application/json" \
-d '{"packages": ["chalk", "zod", "axios", "lodash"]}'
Each result now includes scorecardScore alongside maintainers, weeklyDownloads, and hasProvenance. Open source on GitHub.
Top comments (0)