In December 2025 npm revoked every long-lived token — the measure the whole effort after that year’s attacks was built around. It worked. And two of the three worm campaigns of 2026 bypassed it entirely, abusing trusted publishing via OIDC: the very control introduced in its place.
Below: the measured figures — 220,139 malicious packages in the open dataset, three quarters of last year’s turning out to be one spam campaign; the absence of classic typosquatting from the 2026 data; and our own measurement of whether what gets found actually gets removed.
On 27 August 2026 we queried the counters directly:
| Measure | Value | What it is |
|---|---|---|
| Packages in the registry | 4,334,379 | documents in the replica, placeholders and unpublished included — an upper bound |
| Downloads in a month | 601,025,022,146 | 27 Jul – 25 Aug 2026 |
| Downloads in a day | 37,969,071,481 | 25 Aug 2026 |
Downloads are not people or organisations. This is request volume against the registry, dominated by build pipelines re-pulling. Sonatype states the same outright: downloads are "a consumption signal, not a proxy for unique users".
Registry growth through 2026 runs at roughly 2,470 packages a day net. "Net" matters: in the second half of 2023 the counter fell by 650,000 as npm purged spam. Publishing cannot be separated from deletion in the public data.
The open OSV dataset holds 220,139 records of malicious npm packages. By year of publication:
| Year | Records | Excluding bulk campaigns |
|---|---|---|
| 2022 | 7,424 | 7,424 |
| 2023 | 2,291 | 2,291 |
| 2024 | 8,372 | 8,372 |
| 2025 | 191,420 | 46,148 |
| 2026 (to 27 August) | 10,627 | 10,627 |
The 191,420 for 2025 is a trap, and must not be quoted without the caveat. Around 140,000 records fall in four days of November and belong to a single spam campaign: packages with auto-generated names published to inflate reputation scores in a third-party token scheme. The OSV records say so themselves.
Sonatype independently describes the same campaign from a different corpus — 169,538 packages "designed to self-replicate every seven seconds". Two measurements, one campaign.
Cleared of those spikes the picture is smaller and more informative: through 2026, roughly a thousand records a month, rising within the year — 329 in February, 2,984 in August.
For scale: PyPI shows 1,298 records for 2026 against npm’s 10,627 — an eightfold gap.
We analysed all 10,627 names flagged in 2026. The result is unexpected:
| Property | Result |
|---|---|
Names without a scope (@org/) | 7,609 (71.6%) |
| Scoped names | 3,018 (28.4%), across 1,078 distinct scopes |
| One letter away from a popular package | 0 of 7,609 |
| Containing a popular package name as a substring | 848 (7.98%) |
Instead of impersonating lodash or express, the dominant pattern is seizing a whole namespace: @antv with 279 records, @servicetitan 141, @cloudplatform-single-spa 122, @mastra 89, @uipath 66.
Those scopes match the year’s known victims exactly. Which follows if the mechanism is: steal access, enumerate everything the account may publish, republish all of it.
Limits of the conclusion: the comparison list held 54 popular names, and "one letter away" is a narrow definition that misses transposition, brand impersonation and compound names. Read this as "in 2026 the threat looks different", not as "typosquatting no longer happens".
After the 2025 attacks npm tightened up, and the sequence matters:
| Date | Change |
|---|---|
| 5 Nov 2025 | new classic tokens blocked, granular tokens capped at 90 days |
| 9 Dec 2025 | all existing classic tokens revoked; login issues a two-hour session; two-factor required for publishing |
| 8 Jul 2026 | npm 12: lifecycle scripts (preinstall, postinstall) off by default |
The measures work: the long-lived tokens exploited in 2025 no longer exist.
And yet two of the three worm campaigns of 2026 bypassed them entirely. The mechanism is abuse of trusted publishing via OIDC — precisely the control introduced in place of tokens. The analysis of the May campaign states it plainly: "every previous wave began with a stolen credential; this one did not". Instead of stealing an account it used a misconfigured build workflow and poisoned its cache.
An unwelcome but important conclusion: killing long-lived tokens did not remove the threat but moved it one floor up — into the build systems that now hold the trust.
The June campaign took that logic to its limit: the substituted versions were published carrying valid provenance attestations. The signature was genuine, because a compromised pipeline signed it.
Every event below was cross-checked against OSV records.
And a sobering detail from 2025. The loudest attack of September 2025, reaching packages with hundreds of millions of weekly downloads, was live about two hours and earned its operators, by independent measurement, roughly five cents of ETH plus twenty dollars of a memecoin. The write-up is titled "Oops, No Victims".
Separately on historical events that are routinely retold wrongly: left-pad (2016) was an availability failure, not an attack — no malicious code was ever involved; and xz-utils (2024) has nothing to do with npm — it is a Linux compression library.
For calendar 2025, on npm:
| Source | Malicious packages |
|---|---|
| ReversingLabs | 10,819 |
| Datadog | 13,994 |
| OSV, spam removed | ~14,000–46,000 |
| OSV, as published | 191,420 |
| Sonatype (all ecosystems) | 454,648 |
The first three agree within a third — the spread to the rest is definitional, not empirical. OSV counts packages, Datadog counts versions; some include spam and others do not; Sonatype blends all registries.
On the headline "malware grew 75%": that is growth of the cumulative total between two report editions fifteen and a half months apart, not year-on-year growth of new detections, which on a comparable base is about 6%. And by Sonatype’s own taxonomy, 83.4% of that 454,648 is spam and junk rather than an attack payload.
The general rule: every such figure is one vendor’s detection capability on that vendor’s corpus. It is a lower bound, not a rate. Nobody publishes a rate, because the denominator is unknown.
Who actually finds them: in the open 2026 dataset, Amazon Inspector (18,026 reports) and GitHub (6,094). Socket, Snyk and Sonatype contribute nothing to it.
We took 200 packages flagged malicious in 2026 and queried each in the registry. 194 answer 200 and six answer 404. But a 200 does not mean the malware is still there: inspecting sixty of them gives:
| State | Packages | Meaning |
|---|---|---|
| npm placeholder | 26 (43%) | content replaced with a security-holding marker |
| Unpublished | 24 (40%) | no versions remain |
| Live legitimate package | 10 (17%) | a compromised project cleaned and restored |
We found no case where the malware is still installable. The ten "live" ones are exactly the affected namespaces such as @qlik and @antv, restored after cleanup.
Caveat: sixty of two hundred were inspected, and we did not diff version histories to confirm the specific infected versions are gone. The claim is "removal appears complete", not "removal is guaranteed complete".
The adjacent subject — dependency depth — is covered in a separate article.
Sources: the OSV/OpenSSF open dataset, the npm registry replica, the download counter, the npm 12 changes.
Minimum. Snyk / Socket.dev / GitGuardian add behavioral analysis + zero-day detection.
package.json reviews in PR, npm install --ignore-scripts (block post-install hooks), allowlists in a registry proxy.
US federal contracts — yes (EO 14028). Enterprise SaaS — often requested. 2026 best practice.
Free plan — 10 monitors, checks every 5 min, no card required. Upgrade for 1-minute interval and multi-region monitoring.