CLI tool
ossf/malicious-packages avatar
ossf/malicious-packages

Malicious packages: a corpus with an argued edge, not a blocklist

A repository of reports of malicious packages identified in Open Source package repositories, consumable via the Open Source Vulnerability (OSV) format.

642 stars178 forksGoApache-2.0

At a glance

What is it?
The OpenSSF malicious-packages repository collects reports of malicious packages in OSV format, and most of its documentation is spent arguing about where the boundary sits. Spam, obfuscation, telemetry, protestware and offensive security tools are each admitted or excluded with a stated reason, which is what makes the corpus usable as a data source rather than a deny list.
Who is it for?
Use this corpus if you are building a detector or maintaining an advisory feed and want training data with a published, contestable definition rather than a vendor's private one. Treat the borderline inclusions as the interesting part: obfuscated and typosquatted packages are present precisely because they are hard to separate from their malicious cousins.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • ossf/malicious-packages642 ★ · +53
Star history
Repository2026-08-042026-11-14
ossf/malicious-packages589642

53 Stars in the last 102 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

It is a report corpus, not something you install or apply

The repository collects reports of malicious packages found in open source package registries, expressed in the Open Source Vulnerability format so the same records can feed the wider OSV tooling. It is closely related to the OpenSSF Package Analysis project, which is where automated analysis of packages lives.

The stated gap is specific. Attacks on open source ecosystems are becoming more frequent each year, typosquatting, dependency confusion and account takeovers among them, and while various security products offer protection, no comprehensive database of malicious packages published to those registries existed. The aim is to be exactly that: comprehensive, high quality and open source.

The repository is the database and the tooling around it. The tree holds an `osv/` directory for the records, `cmd/` for the commands, `internal/`, `config/`, `docs/` and a `site/` for the statistics page, plus a Makefile, a golangci configuration and two contribution documents. It is Apache-2.0 licensed, written in Go, and the module requires Go 1.25.8.

The definition is two conjunctions, and one clause is about removal

A package counts as malicious here if it is publicly available in a registry and either would require incident response when installed or used, through loss of confidentiality, availability or integrity, or exfiltrates an identifier that can be used to attack the victim afterwards, such as a username for phishing or a password for bruteforcing.

It must then also either violate the terms of the registry it lives in, or be reasonably considered to require removal from that registry. That second conjunction is the unusual one, and it is why registry policy is part of the security judgement rather than a separate matter.

The consequence is visible in the scope list, which starts from packages in any ecosystem the OSV Schema supports, then adds typosquatting publications, account takeovers, malicious prebuilt binaries shipped inside a package, security researcher activity, and dependency or manifest confusion. What is out of scope is equally explicit: non-malicious packages, vulnerability reports, compromised infrastructure, and offensive security tools unless they execute a malicious payload on install.

Spam and typosquatting are admitted, and that is a decision

The borderline section says plainly that typosquatting or spam packages that are empty or trivial, while not malicious, are allowed to be present in the dataset. The reason given is classification difficulty: typosquatting packages may be hard to distinguish from dependency confusion, so the reports are allowed in.

That reasoning extends to the spam cases themselves. Spam and typosquatting are not malicious unless the package exhibits malicious behaviour under the definition, and such packages are often empty with no functional code, or do something trivial such as printing a message. They are described as a nuisance and generally unwanted, which is a different problem from a security incident.

The two attack types are grouped together in the documentation for a second reason. Dependency confusion is effectively the same as an account takeover where an attacker replaces a package's code with their own, which means even a trivial or empty dependency confusion package would require incident response. Manifest confusion needs someone to bypass the npm command line tool and deliberately supply an altered manifest. Very occasionally a developer stumbles into these quirks unintentionally, and the documentation calls that infrequent.

Obfuscation is in scope only where a registry forbids it

Reverse engineering protection gets the longest treatment of any borderline category, and the argument is that the technique itself is neutral. Obfuscation and debugger evasion are used both by developers protecting their source and by attackers evading detection, so their presence is not evidence of intent.

What settles it is registry policy. Reports of obfuscated packages are allowed even when they are not clearly malicious, if the package belongs to an ecosystem where obfuscation is forbidden in the terms of use, with PyPI and Crates.IO given as the examples.

That produces a slightly uncomfortable but defensible position: a dataset that includes some packages it cannot prove are malicious, on the grounds that in those two registries the practice itself breaches the rules. Anyone training a classifier on this corpus should know that, because a false positive rate measured against these records is not a measurement against proven attacks.

Telemetry and protestware turn on effect, not on intent

Telemetry on its own is not malicious, since many open source packages track installs or behaviour and performance. It becomes malicious when it is abused to exfiltrate sensitive data or to provide remote access.

Protestware follows the same test, stated in terms of what the package does to the systems it runs on. A message logged to the console may annoy a developer, but it does not affect availability, integrity or confidentiality, so it is not malicious. Protestware that destroys files, slows performance, or otherwise degrades those properties as part of the protest may be considered malicious.

The through-line is that intent is not part of the test at all. A package can be a political statement and be excluded, or be an innocuous developer convenience and be included, depending only on whether it costs the victim something. That is what lets the corpus be consumed as evidence rather than as a list of opinions.

Offensive tools are excluded unless they drop a payload

Offensive security tools, libraries and hacking tools are not malicious. Finding one in an environment may indicate a compromise, but the package itself is not the problem: such packages do not necessarily violate the terms of the registries hosting them, and security researchers use them legitimately.

The exception is installation behaviour. An offensive security tool that executes a malicious payload while being installed is a malicious package, which is a clean line to draw and one that follows from the definition rather than from taste.

This category is where a feed consumer is most prone to false alarms, because a scanner that matches on package name will flag the same artifact a researcher installed on purpose. The corpus records the distinction; whether a downstream tool preserves it is that tool's problem.

The Makefile is the entire operational surface

There are four things worth running, and all of them are Make targets reading a config file:

code
go test -race './...'
go run ./cmd/validate -config ./config/config.yaml
go run ./cmd/preprocess -config ./config/config.yaml
go run ./cmd/preprocess -config ./config/config.yaml -abort-unmergable

Validation checks every OSV file in the repository. Preprocessing runs before IDs are assigned, and the strict variant aborts when it hits reports that cannot be merged, which is the flag to reach for when you want a hard failure instead of a warning.

The default target is not any of those but `help`, which is generated by an awk one-liner over the Makefile itself to print a coloured target list. That is the only flourish in the build.

The Go side reflects where the records come from. The module depends on both the Google Cloud storage client and the AWS S3 client, along with `gocloud.dev`, which is how one ingestion path can read from either bucket. It also depends on the OSV schema bindings, the package-url library, the urfave CLI, go-git, protobuf and YAML.

Growth comes from bulk pull requests and automated sources

Reports arrive by pull request, and both new reports and updates to existing ones are accepted. Bulk imports are accepted too, with one condition: open an issue first so the shape of the data can be discussed before thousands of records arrive.

There is a second channel for data that already exists. If you regularly produce high quality detections with few false positives and are accumulating them in a database, the project will consume them automatically as OSV from cloud storage, with S3 and GCS named. That is a notable design choice, because it means the pipeline accepts a feed from a third party rather than requiring every contribution to pass through review.

The statistics page at ossf.github.io is described as automatically updated daily, so the corpus is meant to be read as current rather than as a snapshot. Communication happens mostly in the OpenSSF Package Analysis Slack channel, with official notices on the OpenSSF working group mailing list for securing critical projects, and the group meets every other Thursday at a time chosen to suit APAC or EMEA.

Editorial conclusion

Use this corpus if you are building a detector or maintaining an advisory feed and want training data with a published, contestable definition rather than a vendor's private one. Treat the borderline inclusions as the interesting part: obfuscated and typosquatted packages are present precisely because they are hard to separate from their malicious cousins. Before you rely on a record, read how the package meets the definition, since the corpus deliberately contains entries a strict reading would leave out, and note that the repository ships no releases and updates as daily commits rather than tagged versions.

Frequently asked questions

What is the ossf/malicious-packages repository?

An Apache-2.0 collection of reports of malicious packages found in open source package registries, written in OSV format and closely related to the OpenSSF Package Analysis project. It exists because no comprehensive public database of malicious packages had been published.

What counts as a malicious package in this repository?

A package publicly available in a registry that would require incident response when installed or used, or that exfiltrates an identifier usable for a later attack, and that either violates the registry's terms or would reasonably be considered to require removal.

Does the malicious-packages dataset include typosquatting and spam packages?

Yes, as a documented borderline case. Empty or trivial spam and typosquatting packages that are not malicious are allowed to be present, because they are hard to distinguish from dependency confusion. Dependency confusion itself counts as malicious even when the package is empty.

Is protestware treated as malicious here?

Only when it affects availability, integrity or confidentiality of the systems it runs on. A message logged to the console is not malicious; protestware that destroys files or degrades performance as part of the protest may be.

How do I contribute reports or an automated feed to malicious-packages?

Open a pull request for a new or updated report, or for a bulk import after opening an issue first. If you already produce high quality detections with few false positives in a database, the project can consume them automatically as OSV from S3 or GCS storage.

Official sources

  1. Official README
  2. Project repository
  3. README
  4. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ossf-malicious-packages.svg)](https://hysenlabs.com/projects/ossf-malicious-packages)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/ossf-malicious-packages.svg)](https://hysenlabs.com/projects/ossf-malicious-packages)

Was this useful?