Check P8 · provenance family · severity MEDIUM · automatic · one of the 12 npm and PyPI package checks
Maps to OWASP LLM03 ATLAS AML.T0012 The latest version published by an account that published none before it: a legitimate handover and a stolen account look the same from the registry.
The question this check asks: who published this version, and have they published this package before? On an established package, a version published by an account that never published an earlier one is a new hand on the package.
A new publisher is how a package changes hands, honestly or otherwise. A maintainer adds a colleague; a project moves to an organisation's account; or an account that should never have had access publishes one release. From the registry's record the three look the same, and the record is all the check reads — so it names the change and leaves the reading to the person installing.
On npm the latest version's publisher (_npmUser) is compared with the publishers of every earlier version in the package's whole record. pkg-new-publisher is MEDIUM and 6 points when the latest version's publisher published none of them, on an established package (first published 90 days ago or more). The finding names the account. A new package's first publishers are not a change, so the check does not read it there. A MEDIUM is a warning under the default profile.
An honest handover. A project that adds a maintainer or moves to an organisation account fires this once, on the first release the new account publishes. The finding names the account so the reader can check it against the project's own announcement.
PyPI. PyPI's JSON names no publisher per release, so this check reads npm only; on a PyPI package it is listed as a stated skip, never a pass. An account that was taken over and publishes under its own name is not a change of publisher, and is not read here; P7 reads the shape that leaves in the history. An npm record too large to read gives no earlier publishers to compare with. The package's code is not read.
Scope, the same on every page of this roster: RepoGates 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. The hook sees Bash tool calls in that one client and nothing else; a package named on the line (npm install express, pip install flask, npx, npm create) is judged by its own verdict under this roster, its declared repository riding along. Direct dependencies named on the command line only; transitive dependencies and lockfiles are not resolved. A package added by editing package.json or requirements.txt and installed later is not a line the hook judges. Edit and Write are read for one thing only — an API key about to be saved — checked on the machine and never sent; that guard asks, it never denies. This roster reads what npmjs.org and pypi.org publish about a package — its record, its release history, its declared repository — and never the package's code or what it installs after it. A registry other than those two (a --registry or --index-url on the line) is asked about, not assessed. A package the registry no longer serves is not assessed, never a pass. A PASS means nothing matched on what was read.
npm view NAME _npmUser maintainers
npm view NAME versions --json
Then look up the earlier versions' publishers (npm view NAME@VERSION _npmUser) and the project's own notes for a handover.
Does a new publisher mean the package was hijacked? No. It is also how a maintainer adds a colleague or moves a project to an organisation account. The check names the account and warns; it does not block.
Why does this check not run on PyPI? Because PyPI's project JSON does not say who uploaded each release, so there is nothing to compare. The check reads npm's record, where each version names its publisher.
Why is a new package not read? Because a package's first publishers are not a change. The check fires only on an established package, first published 90 days ago or more, where earlier versions exist to compare with.
P7 Dormant then released · P1 Known malicious · C5 Contributor concentration.
Add RepoGates to Chrome Pricing
Sources for this page: the rule and weights from the product's own roster and scoring tables.