Threat model and measurement · this page 31 October 2026
The shape. A package that runs code when it is installed,
published under a name one letter away from a popular one, or taken
over from its maintainer, reaches a developer the moment
npm install or pip install runs. An AI
coding agent types those commands for you. The campaigns RepoGates
lists are reported in OSV's malicious-package records
(MAL- entries) and by researchers such as
JFrog's testmetest report,
whose 15 npm package names are on the campaign blocklist.
Twelve checks, read from the registry's own record and never from the package's code (the list):
MAL- record names the package. Critical; the
verdict is BLOCK. Only the package's name is sent to OSV.A package the registry no longer serves is not assessable, never a
pass. Since 31 October, OSV is asked about such a name too, and a
MAL- record blocks it, because a removed name can be
registered again.
| List | Packages | PASS | REVIEW | BLOCK |
|---|---|---|---|---|
| npm, most depended on | 200 | 186 | 14 | 0 |
| PyPI, most downloaded | 200 | 189 | 11 | 0 |
Most REVIEWs on npm are a new publisher on the latest release (a maintainer change, read from npm's record); most on PyPI are a name the declared repository's manifest does not carry (monorepos). Neither list had a BLOCK. We also ran 98 npm and 100 PyPI packages from the OSV malicious-package dataset: none passed. Most PyPI samples had been removed from the registry and were "not assessed"; that is what led to the OSV lookup for removed names above, which has not been re-measured yet.
In Claude Code with the RepoGates plugin, npm install,
pip install, npx and npm create
lines are checked before they run; the MCP server answers the same
question for any agent that asks. On npmjs.com and pypi.org pages the
verdict is answered through the agent surfaces, not the browser
board.
It does not see git clone, package managers or
curl — outside Claude Code with the RepoGates plugin, whose
hook refuses a clone or install that names a blocked repository on the
command line, before it runs. Direct dependencies named on the command
line only; transitive dependencies and lockfiles are not resolved. It
does not read a package's code or what the package installs after it,
and a clean result is not an audit.