Research

Research report · Cloud, application and infrastructure security

Poisoned dependencies: what 232,930 malicious-package reports say about open-source supply chain risk

An analysis of every malicious-package record in the OSV database from January 2023 to November 2026, with a registry check of how long harmful npm packages stayed available.

Report
EFF-RR-2026-008
Published
12 November 2026
Version
1.0
Authors
Effycace Research Team
Reading time
13 min
Distribution
TLP:CLEAR

1Executive summary

Modern software is assembled from open-source packages downloaded from public registries such as npm and PyPI. Attackers publish malicious packages there, and occasionally take over trusted ones. Each discovery is recorded in public databases, and the largest of these, OSV, now holds hundreds of thousands of malicious-package records.

We analysed all 232,930 malicious-package records published in OSV between January 2023 and 12 November 2026 across eight ecosystems, classified each by what it reportedly does, tested which PyPI names imitate popular projects, and checked a random sample of npm records against the registry to measure how long harmful packages stayed available. Most records turn out to be spam; the real threat is smaller, mostly theft, and stays available for weeks.

Key findings

  1. Most malicious-package records are spam, not attacks. 60.6% of the 232,930 records are token-farming spam, and 99.7% of those were filed in a single month, November 2025. Raw counts of "malicious packages" therefore say little about risk.

    High confidenceSee the evidence

  2. Where the behaviour of harmful packages is described, 81.5% steal something: credentials, tokens, browser data or cryptocurrency. But 59.1% of harmful records give no detail at all.

    Moderate confidenceSee the evidence

  3. Trusted packages are compromised in waves. 2,155 records concern legitimate packages taken over, concentrated in five bursts between September 2025 and August 2026, several of them self-spreading worms.

    High confidenceSee the evidence

  4. Harmful npm packages stayed available for a median of 35 days before npm removed them, and only 15.5% were removed within a day. In 71% of cases npm acted before the OSV record appeared, so feeds built on OSV mostly arrive after the fact.

    Moderate confidenceSee the evidence

  5. Typosquatting is a minority tactic. Only 9.6% of malicious PyPI names imitate one of the 15,000 most-downloaded projects; checks for look-alike names alone would miss nine in ten.

    Moderate confidenceSee the evidence

What this means

Boards and executives
Open-source components are part of the supply chain and need the same oversight as other suppliers. Ask whether the organisation knows which packages it uses, where they come from, and how quickly it can find and contain a bad one.
Security leaders
Plan on the basis that a malicious package will be installed before any public feed flags it. Prioritise controls that limit what an install can reach, and a tested process to find past installs and rotate the credentials they could have taken.
Engineering teams
Pull packages through a controlled registry, pin versions with lockfiles, turn off install scripts by default, keep secrets out of build environments, and protect your own publishing accounts with trusted publishing and strong multi-factor authentication.

2Scope and questions

Research questions

  1. How many malicious packages are reported in the main open-source registries, and how much of that is a genuine threat?
  2. What do harmful packages do, and how do attackers get them installed?
  3. How long do harmful packages stay available, and how early do public feeds warn defenders?

In scope

  • All 232,930 malicious-package (MAL-) records in OSV published from 1 January 2023 to 12 November 2026, after excluding 363 withdrawn records and two marked as false positives
  • Eight ecosystems: npm, PyPI, RubyGems, NuGet, crates.io, Go, Maven and Packagist
  • A fixed random sample of 600 npm records from 2025 and 2026 (300 harmful, 300 spam), checked against the npm registry on 12 November 2026

Out of scope

  • How many times each package was downloaded or installed, which OSV does not record
  • Vulnerabilities in legitimate packages (non-malicious flaws), which are covered in reports EFF-RR-2026-001 and EFF-RR-2026-002
  • Removal times outside npm: PyPI and the other registries delete malicious packages without leaving a record of when

3Methodology

We downloaded the OSV dumps for eight ecosystems on 12 November 2026 and kept every record whose identifier begins with MAL-, the prefix OSV uses for malicious packages imported from the OpenSSF malicious-packages project. Records that were withdrawn or marked as false positives were excluded.

Each record was classified by written rules applied to its summary and description, in a fixed order with the first match winning: spam and token farming; compromised legitimate packages; dependency confusion and reconnaissance; cryptocurrency theft; credential and data theft; malware delivery and remote access; contact with a known malicious domain; and, where none applied, malicious with no detail given. We call every category except spam and reconnaissance "harmful". The rules were refined by reading samples of matched text; for example, an early rule for compromised packages also caught a package named hijack_publish and was removed.

For PyPI, we compared each harmful name with the 15,000 most-downloaded projects (ranking dated 1 November 2026), counting a name as imitating one if it matched exactly; was a close misspelling of a top-5,000 project of five or more characters (the two names become identical after deleting at most one character from each, or after swapping two neighbouring letters); or combined a top-1,000 project name with other words. For npm, we checked 300 harmful and 300 spam records from 2025 and 2026, drawn with a fixed random seed, against the registry. When npm removes a malicious package it replaces it with a placeholder version, 0.0.1-security, and keeps the publication times of the original versions. We treat the placeholder time as the removal time and measure from the first published version.

Sources

SourceHow it was usedReliability
OSV database dumps, eight ecosystems, retrieved 12 November 2026Every malicious-package record: package, ecosystem, publication date, description and reporting source.Authoritative aggregator. Content depends on what reporters submit, and many descriptions are generic.
OpenSSF malicious-packages projectThe upstream source of the MAL- records, and the reporters credited for each.Primary open data. One automated reporter accounts for most records.
npm registry metadata, 600 sampled packages, 12 November 2026Version publication times and the time of npm’s security placeholder for each sampled package.Primary source for timing; the placeholder time is taken as the removal time.
Top PyPI Packages (30-day download ranking, 1 November 2026)The 15,000 most-downloaded PyPI projects, used to test name imitation.Widely used community dataset derived from PyPI download statistics. Reflects current, not historical, popularity.

Review

  • Author review: Effycace Research Team, authoring team

Data availability

Counts by ecosystem, year and category (counts.csv), every PyPI name that imitates a popular project (pypi-name-imitation.csv), the 600-record npm registry sample with its timestamps (npm-registry-sample.csv), every figure in this report (results.json) and the analysis code with its classification rules (analyse.txt) are free to download. The OSV dumps themselves are public.

4Findings

Finding 1

Most malicious-package records are spam, and npm dominates

High confidence

Of the 232,930 records, 141,131 (60.6%) describe spam: packages mass-published to farm rewards from the tea.xyz token scheme rather than to attack the people who install them. Almost all of it is on npm, and 140,728 of those records (99.7%) were filed in November 2025, when the campaign was flagged in bulk. A chart of "malicious packages per year" is mostly a chart of that one event.

The remaining 89,865 records (38.6%) describe harmful packages; a further 1,934 describe dependency-confusion probes and other reconnaissance, which we report separately. Harmful records rose from 8,757 in 2023 to 51,710 in 2025, and reached 17,468 in 2026 by 12 November.

npm accounts for 92.7% of all records and 82.3% of harmful ones. PyPI follows with 10,747 harmful records, then RubyGems (4,307) and NuGet (782). RubyGems shows the sharpest recent change: 3,372 harmful records in 2026, against 128 in 2025. The other four ecosystems together have 45.

Table 1Malicious-package records by ecosystem, January 2023 to 12 November 2026
EcosystemAll recordsSpamHarmfulHarmful in 2026
npm215,814140,91373,98412,859
PyPI11,97321710,7471,182
RubyGems4,31614,3073,372
NuGet782078222
crates.io, Go, Maven, Packagist4504533
All ecosystems232,930141,13189,86517,468

Base: OSV MAL- records published 1 January 2023 to 12 November 2026, excluding 363 withdrawn and 2 false-positive records. Spam and harmful do not sum to all records because reconnaissance (1,934) is shown separately. Source: OSV dumps retrieved 12 November 2026.

Finding 2

Harmful packages mostly steal, but most records do not say what they do

Moderate confidence

Of the 89,865 harmful records, 53,071 (59.1%) say only that a package is malicious, often with a stock sentence that any computer running it should be considered compromised. That gap limits what defenders can learn from the data: a blocklist entry with no behaviour cannot tell a team which secrets to rotate.

Among the 36,794 records that do describe behaviour, theft dominates. Credential and data theft, such as stealing tokens, environment variables, browser data and SSH keys, accounts for 74.3%, and cryptocurrency theft for a further 7.2%: 81.5% in all. Contact with known malicious domains (9.0%), compromised legitimate packages (5.9%) and malware delivery or remote access (3.6%) make up the rest.

The emphasis on theft matters for response. Code of this kind typically runs when a package is installed or first imported on a developer laptop or build server, which is where tokens and cloud credentials live. Removing the package afterwards does not undo what it has already sent away.

Figure 1What harmful packages do, where the record describes it
  • Credential and data theft74.3%
  • Contacts a known malicious domain9.0%
  • Cryptocurrency theft7.2%
  • Compromised legitimate package5.9%
  • Malware delivery and remote access3.6%

Base: 36,794 harmful records whose description states a behaviour; 53,071 further harmful records give no detail. Category assigned by Effycace rules applied to each record’s text, published with the dataset. Source: OSV dumps retrieved 12 November 2026.

Finding 3

Trusted packages are compromised in waves

High confidence

2,155 records concern legitimate packages that attackers took over, typically by phishing a maintainer or stealing a publishing token, and then used to push a malicious version to everyone who depended on them. They are few compared with the total, but each can reach far more systems than a new package with an invented name.

They arrive in bursts. The records cluster in September 2025 (230), when widely used packages including ansi-regex, ansi-styles and DuckDB’s were compromised, the DuckDB case through a phishing attack on a maintainer, according to the records; November 2025 (793), described in the records as the "Sha1-Hulud: The Second Coming" worm; March 2026 (69, "CanisterWorm"); May 2026 (533, mostly "Mini Shai-Hulud"); and August 2026 (454, "Shai-Hulud: here we go again"). Several of these campaigns spread by themselves, using tokens stolen from one maintainer to publish to that maintainer’s other packages.

Defences based on suspicious names cannot catch these, because the name is the trusted one. What helps is limiting what any install can do, pinning versions so that a new release is not pulled in automatically, and protecting publishing accounts so that the next maintainer does not become the next source.

Figure 2Records of compromised legitimate packages, by month of the five main waves
  • September 2025230
  • November 2025793
  • March 202669
  • May 2026533
  • August 2026454

Base: 2,155 records classed as compromised legitimate packages, of which 2,079 fall in these five months. Campaign names are as given in the records. Source: OSV dumps retrieved 12 November 2026.

Finding 4

Harmful packages stay available for weeks, and feeds learn late

Moderate confidence

Of 300 harmful npm records from 2025 and 2026, drawn at random, npm had replaced 253 (84.3%) with its security placeholder, 28 (9.3%) had been unpublished, 12 (4.0%) were not found and 7 (2.3%) were still available. For the 238 removed packages with recorded timestamps, the median time from first publication to removal was 35 days. Only 15.5% were removed within 24 hours, and 52.1% stayed available for more than 30 days. Most (79.4%) had a single version, so the clock starts with the malicious release itself.

Public feeds lag further. In 71.0% of these cases npm removed the package before the OSV record was published. A blocklist built on OSV therefore mostly confirms what the registry has already done; its main value is in finding past installs, not preventing new ones.

This also tests a common control: refusing packages younger than a minimum age. A seven-day minimum would only have stopped the 22.7% of harmful packages that npm removed within a week. It is worth having, but not on its own. Spam behaves differently again: 45.3% of the sampled spam packages were still available, and those that npm had removed had stayed up for a median of 547 days.

Figure 3Time harmful npm packages stayed available before removal
  • Within 24 hours15.5%
  • 1 to 7 days7.2%
  • 8 to 30 days25.2%
  • More than 30 days52.1%

Base: 238 harmful npm packages from a random sample of 300 records published in 2025 and 2026, removed with a security placeholder and with version timestamps. Measured from first version publication to placeholder publication. Source: npm registry, queried 12 November 2026; OSV dumps.

Finding 5

Look-alike names are a minority tactic

Moderate confidence

Typosquatting, publishing a package whose name is a slip of the keyboard away from a popular one, is the best-known way to get malware installed. In PyPI it is real but small. Of 11,756 harmful and reconnaissance records, 964 (8.2%) are close misspellings of a top-5,000 project, 159 (1.4%) combine a popular name with other words, and 8 (0.1%) use the exact name of a top-15,000 project, which usually means that project was itself compromised. In total, 9.6% imitate a popular project.

The most imitated names are the most widely used libraries: requests (109 imitations), beautifulsoup4 (53), colorama (44), requests-toolbelt (43) and websocket-client (40). The other 90.4% use names that do not resemble a popular project. How those packages reach their victims is mostly not recorded in the data.

Name-similarity checks are cheap and worth running, but a control that only flags look-alikes would miss nine in ten malicious packages. Knowing why each new dependency is needed, and who added it, catches more.

Table 2Most-imitated PyPI projects among malicious package names
Popular projectMalicious imitationsExample
requests109erquests, requests-flask, google-requests
beautifulsoup453bautifulsoup4, beatuifulsoup
colorama44clorama, coloarma
requests-toolbelt43reqeusts-toolbelt
websocket-client40webocket-client

Base: 1,131 of 11,756 harmful and reconnaissance PyPI records whose names imitate a project in the top 15,000 by 30-day downloads (ranking of 1 November 2026). Popularity is current, not as at the time of each attack. Source: OSV dumps; Top PyPI Packages.

5Recommendations

Recommendations are ordered by priority. Effort is a broad estimate for a mid-sized organisation; your own will depend on what is already in place.

#RecommendationOwnerPriorityEffortFramework reference
1Install packages only through a controlled internal registry or proxy that can block known-malicious versions and hold new packages for review.Engineering platform teamHighMediumNIST SSDF PW.4
CIS Controls v8.1 16.4
2Pin dependencies with lockfiles and turn off install scripts by default, allowing them only for packages that need them.Engineering leadsHighLowNIST SSDF PS.1
npm ignore-scripts
3Keep long-lived secrets out of developer and build environments; use short-lived, narrowly scoped credentials so that a stolen token is of little use.Security architectureHighMediumNIST CSF 2.0 PR.AA-05
4Protect your own published packages with trusted publishing and phishing-resistant multi-factor authentication on maintainer accounts.Package maintainersHighLowPyPI and npm trusted publishing
NIST SSDF PS.1
5Keep a software inventory (SBOM) for each application and check it daily against the OSV malicious-package feed; when a match is found, treat it as an incident and rotate every credential the affected machine could reach.Security operationsMediumMediumNIST CSF 2.0 ID.AM-02, RS.MI-02
6Add a minimum package age and look-alike name checks to dependency review, as supplements rather than the main defence.Engineering leadsMediumLowCIS Controls v8.1 16.4

6Limitations

  • OSV records reflect what reporters submit. One automated reporter, Amazon Inspector, is credited on 58.1% of harmful records, and only 7.1% of all records have more than one reporter, so the data shows what scanners find more than what attackers attempt.
  • Categories come from rules applied to each record’s text. 59.1% of harmful records have no usable description, and the boundary between spam, reconnaissance and harm is sometimes a judgement. The rules are published so readers can test other choices.
  • Records count packages, not installations. A package downloaded once and one downloaded millions of times count the same.
  • Removal times come from a random sample of 300 harmful npm records and assume that npm publishes its security placeholder when it removes a package. Packages first published before 2025 but recorded later are included and lengthen the tail. Other registries leave no removal timestamp, so they are not measured.
  • The PyPI popularity ranking is from November 2026 and the imitation test catches only close spellings and simple combinations; other imitation styles are counted as not imitating.
  • This report was reviewed by its author and has not yet been independently peer reviewed. We welcome corrections and will record them in the version history.

7How to read this report

Each finding carries a confidence level, which describes the quality of the evidence behind it. Where we estimate likelihood, we use fixed terms so that “likely” means the same thing every time.

High confidence
Based on good-quality information from several independent sources, or on a complete dataset. A high-confidence judgement can still be wrong.
Moderate confidence
Based on credible information, but with gaps, a limited sample or more than one plausible interpretation.
Low confidence
Based on scarce, fragmented or single-source information. Treat it as something to watch, not as the sole basis for a major decision.
TermProbability
Almost no chance1–5%
Very unlikely5–20%
Unlikely20–45%
Roughly even chance45–55%
Likely55–80%
Very likely80–95%
Almost certain95–99%

8References

  1. OSV. Open Source Vulnerabilities database. https://osv.dev/
  2. OSV. Data dumps and downloads. Retrieved 12 November 2026. https://google.github.io/osv.dev/data/
  3. Open Source Security Foundation. OpenSSF malicious-packages project. https://github.com/ossf/malicious-packages
  4. Open Source Security Foundation. OSV schema. https://ossf.github.io/osv-schema/
  5. van Kemenade, H. Top PyPI Packages: 30-day download ranking, updated 1 November 2026. https://hugovk.github.io/top-pypi-packages/
  6. MITRE. CWE-506: Embedded Malicious Code. https://cwe.mitre.org/data/definitions/506.html
  7. National Institute of Standards and Technology. (2022). Secure Software Development Framework (SSDF) Version 1.1. NIST SP 800-218. https://doi.org/10.6028/NIST.SP.800-218
  8. National Institute of Standards and Technology. (2024). The NIST Cybersecurity Framework (CSF) 2.0. NIST CSWP 29. https://doi.org/10.6028/NIST.CSWP.29
  9. Center for Internet Security. CIS Critical Security Controls, version 8.1. https://www.cisecurity.org/controls/v8-1
  10. Python Packaging Authority. PyPI: Trusted Publishers. https://docs.pypi.org/trusted-publishers/
  11. npm. Trusted publishing for npm packages. https://docs.npmjs.com/trusted-publishers
  12. npm. CLI configuration: ignore-scripts. https://docs.npmjs.com/cli/v11/using-npm/config

9About this report

Author
Effycace Research Team, Effycace Solutions
Funding and interests
This report was funded by Effycace Solutions. No registry, reporter or vendor named in it sponsored, reviewed or approved it. Package and campaign names are as recorded in public data and do not imply wrongdoing by the legitimate maintainers whose packages were compromised.
Distribution
TLP:CLEAR This report may be shared freely, with attribution.
Corrections
If you find an error, write to contact@effycace.com. Corrections are recorded in the version history below.

How to cite

Effycace Research Team (2026). Poisoned dependencies: what 232,930 malicious-package reports say about open-source supply chain risk (Report EFF-RR-2026-008, version 1.0). Effycace Solutions Pte Ltd. https://www.effycace.com/research/reports/malicious-packages-2023-2026/

Version history

VersionDateChange
1.012 November 2026First published.

This report is general information, not advice for your specific circumstances. See our Terms of Use.

Want to discuss what this means for you?

We can walk your team through the findings and how they apply to your environment.

Request a Consultation