Is OSV enough for agent artifacts? Measuring how many malicious MCP servers and skills appear in open malicious-package data
OSV-based tooling covers agent artifacts only when they ship through a package registry. The threat.cafe editors joined the 10 incidents in the 2026 agent-ecosystem incident ledger to a snapshot of the OpenSSF malicious-packages repository taken on 15 October 2026. Six of the 10 have a malicious-package report. All six were distributed through npm. The four with no report are the two skill-store campaigns, a trojanised MCP server spread through GitHub and MCP Market, and fake installers on GitHub. None of those four has a registry name for a report to attach to.
The headline number is 6 of 10. The useful number is 0 of 4.
Six out of ten sounds like decent coverage. It is the wrong summary.
The six covered incidents share one property: each artifact had an npm package name and version. The four uncovered incidents share the opposite property. Their artifacts lived in skill stores or GitHub repositories, where the OSV format has no package identity to record.
So the split is not random. It follows the distribution channel. If your agents pull skills from ClawHub or skills.sh, or clone MCP servers straight from GitHub, an OSV-fed scanner has nothing to match against for that traffic.
What the OpenSSF database is built to hold
The OpenSSF Malicious Packages project describes itself as "a collection of reports of malicious packages identified in Open Source package repositories" in OSV format (OpenSSF malicious-packages README). Two lines in its scope rules decide the outcome of this study:
- In scope is "any package that belongs to an ecosystem supported by the OSV Schema."
- A malicious package is defined, first, as "a package publicly available in a package registry."
Vulnerability reports and compromised infrastructure are out of scope (pkg.go.dev mirror of the project).
The OSV Schema's ecosystem list held 53 entries at the 15 October 2026 commit of the osv-schema repository. It includes npm, PyPI, crates.io, Go, Maven, RubyGems, VSCode and GitHub Actions. It does not include ClawHub, skills.sh, the official MCP Registry, or any skill or MCP marketplace.
The data, sliced by ecosystem
The repository snapshot (main branch, commit 216eb47, pulled 15 October 2026) held 238,638 malicious reports. The distribution is extremely skewed:
Ecosystem Reports Share of 238,638
--------------------- ---------- ----------------
npm 222,188 93.1%
PyPI 11,811 4.9%
RubyGems 4,304 1.8%
NuGet 269 0.1%
crates.io 21 <0.1%
Go 20 <0.1%
VSCode + Open VSX 21 <0.1%
Maven 2 <0.1%
Packagist 1 <0.1%
Git (repository URL) 1 <0.1%
Skill stores / MCP registry 0 0%
The Git row matters. OSV can describe a malicious repository through a GIT range with a repository URL, and the snapshot contains exactly one such report, a typosquat of a Go database package. The mechanism exists for GitHub-hosted artifacts. It is almost unused.
A name search adds texture. 218 reports name a package containing the string "mcp" (144 npm, 73 PyPI, 1 RubyGems), and 122 of those carry MAL-2026 identifiers. MCP servers distributed as packages are clearly entering the data. A search for "skill" returns 45 reports, but most are randomly generated spam names such as skilled_..., not agent skills.
The join: ledger row by ledger row
Each ledger row was matched by exact package name and checked for affected versions.
# Incident Channel OSV report Published (UTC)
-- ------------------------------- ------------------- ----------------------- ----------------
1 postmark-mcp 1.0.16 npm MAL-2025-47604 2025-09-26
2 ClawHavoc (341 skills) ClawHub none, no ecosystem -
3 ToxicSkills (76 malicious) ClawHub, skills.sh none, no ecosystem -
4 Oura Ring MCP clone GitHub, MCP Market none found -
5 Fake OpenClaw installers GitHub repos none found -
6 @iflow-mcp/watercrawl-...-mcp npm MAL-2026-1930 (1.3.0-4) 2026-03-19
7 axios 1.14.1, 0.30.4 npm MAL-2026-2307 2026-03-31 03:15
8 mcp-server-todo npm MAL-2026-2328 2026-04-01
9 TanStack packages (Mini Shai- npm 42 reports under 2026-05-11 (e.g.
Hulud II) @tanstack/, e.g. MAL-2026-3465)
MAL-2026-3465
10 brave-search-mcp-server 1.0.0 npm MAL-2026-5182 2026-06-03
By artifact type, the result is binary:
- Packages and package-distributed MCP servers: 6 of 6 covered.
- Skills in skill stores: 0 of 2 covered.
- GitHub-hosted MCP clones and installers: 0 of 2 covered.
The covered rows are well covered. The axios report merges three upstream sources (GitHub's malware advisories, Google's open source security team, and Amazon Inspector) and lists command-and-control indicators. The watercrawl report lists all five malicious versions. Row 4 was searched by name; no report under any "oura" MCP package exists in the snapshot.
Competing explanations
Ledger selection. The ledger includes only incidents with a primary source the editors could open. Quiet registry takedowns never reach it. That probably under-counts npm incidents, which would make OSV look better, not worse.
Skill campaigns are bigger per row. Rows 2 and 3 each stand for dozens to hundreds of malicious skills. Snyk confirmed 76 malicious payloads among 3,984 skills scanned on ClawHub and skills.sh, and 8 were still live when it published (Snyk, 5 February 2026). Counted by artifact rather than by campaign, the uncovered share would be far larger than 4 of 10.
Some skills do reach OSV indirectly. When a skill campaign ships a helper through npm or PyPI, that helper can get a report. The skill that told the agent to install it does not.
Methodology and limits
Denominator: the 10 rows of the threat.cafe incident ledger, September 2025 to June 2026. Ten is a small base; treat shares as descriptive.
Data: the osv/malicious tree of the OpenSSF repository at commit 216eb47, listed with git ls-tree; individual reports read with git show. Ecosystem list from ecosystems.json in the osv-schema repository.
Matching: exact package name, then affected versions. Name searches for GitHub-hosted rows (Oura, OpenClaw installers, ClawHavoc skill names) found no matching report. Several unrelated npm packages with "openclaw" in the name do have reports; they were not counted as matches.
Not tested: commercial feeds that extend OSV, and OSV.dev's other imported sources. The OpenSSF repository is the open baseline most scanners consume.
What this means for your scanner
If your agent gateway or CI step checks OSV, ask three questions of each agent artifact type you allow:
- Does it have a registry name and version? If yes, OSV coverage is real and often fast. In the axios case, the GitHub malware advisory was imported into the repository about six minutes after its own publication.
- Does it come from a skill store? If yes, OSV has no key to match. You need a separate known-bad source and a review step.
- Does it come from a Git URL? OSV can express it, but almost nobody reports it. Treat it as uncovered.
How to close the gap upstream
The fastest route to better open data is contribution, not replacement. The project accepts new reports by pull request under osv/malicious/[ecosystem]/[package_name]/, and asks that each report name a single package and its malicious versions, explain why it is malicious and how the payload triggers, credit the source, and list indicators of compromise (CONTRIBUTING.md). Teams with a steady stream of high-quality detections can ask to have them consumed automatically from cloud storage.
For GitHub-hosted malicious MCP servers, a report with a GIT range is possible today. For skills, the missing piece is an ecosystem identifier. That proposal belongs with the osv-schema maintainers, and skill-store operators are the obvious co-authors.
What would change this finding: a skills ecosystem added to the OSV Schema, a skill store publishing takedowns in OSV format, or a wave of GIT-range reports for MCP repositories.
The threat.cafe list is being built as OSV-format data that also records skills and MCP servers; if you have an artifact that fits none of the existing ecosystems, the board takes reports and credits the finder.
Sources
- ossf/malicious-packages repository, README and CONTRIBUTING.md — OpenSSF, main branch commit 216eb47, 15 October 2026
- malicious-packages — OpenSSF, via pkg.go.dev, accessed 15 October 2026
- ossf/osv-schema repository, ecosystems.json — OpenSSF, 15 October 2026
- MAL-2025-47604: Malicious code in postmark-mcp (npm) — OSV, 26 September 2025
- MAL-2026-1930: Malicious code in @iflow-mcp/watercrawl-watercrawl-mcp (npm) — OSV, 19 March 2026
- MAL-2026-2307: Malicious code in axios (npm) — OSV, 31 March 2026
- MAL-2026-2328: Malicious code in mcp-server-todo (npm) — OSV, 1 April 2026
- MAL-2026-3465: Malicious code in @tanstack/react-router (npm) — OSV, 11 May 2026
- MAL-2026-5182: Malicious code in brave-search-mcp-server (npm) — OSV, 3 June 2026
- Snyk Finds Prompt Injection in 36%, 1467 Malicious Payloads in a ToxicSkills Study of Agent Skills Supply Chain Compromise — Snyk, 5 February 2026