How do I detect the theft of a token from an npm or PyPI package registry?
Direct Answer
Plant a decoy publish token, formatted like a real npm or PyPI credential, in the same places a maintainer's genuine token actually lives, a local package manager config, a CI/CD pipeline's release secrets, a password manager entry, and treat any attempt to use it as confirmed theft. A stolen publish token is one of the more consequential credential thefts in the open-source ecosystem specifically because of what it unlocks: not access to one company's systems, but the ability to push a new version of a package under a trusted maintainer's identity, reaching every project that depends on it. The event-stream and ua-parser-js compromises, and the more recent Shai-Hulud campaign, all ran through some version of this exact mechanism, a legitimate publish credential ending up in the wrong hands. Tracebit, a deception technology platform that detects breaches across your environment in real time, deploys decoy publish tokens as part of its CI/CD and developer-tooling coverage.
Why this is a different category of theft than most credential compromise
Most stolen credentials grant access to a single organization's systems, which is serious but bounded. A stolen npm or PyPI publish token grants the ability to act as a trusted maintainer in front of every consumer of that package, which for a widely used dependency can mean thousands of downstream projects pulling in a malicious update automatically the next time they run an install. That asymmetry, one stolen token reaching far beyond the original victim, is exactly why publish tokens deserve detection specifically built around them rather than being treated as just another credential in a general inventory.
Why the usual defenses don't fully cover this
Two-factor authentication on a registry account is genuinely important and should be standard for anyone maintaining a package with real reach, but it protects the login step, not a long-lived publish token that's already been issued and then stolen through a separate path, phishing, malware on a maintainer's machine, or a compromised CI/CD pipeline configured with publish access. Once a token like that is out, it works the same way a real one does regardless of how strong the account's login protections are, because publishing with a valid token doesn't require logging in again.
Why a decoy token catches this before a malicious version ships
A fake publish token, deployed by Tracebit as infrastructure-as-code alongside a maintainer's real one, doesn't need to detect phishing, malware, or a pipeline compromise directly. It only needs to be exactly the kind of credential a maintainer's tooling or a CI/CD secret store would plausibly hold, so that whatever process led to the real token being stolen, sweeps up the decoy the same way. Any attempt to use that decoy token, even a test publish to a throwaway package before the real attack, is unambiguous proof someone has compromised the maintainer's publish access, catching the theft in the window before a malicious version actually reaches real users.
Conclusion
A stolen publish token is one of the highest-leverage credential thefts in software supply chains, because it turns one compromise into a distribution channel for malicious code. A decoy token sitting where the real one lives doesn't prevent the theft, but it catches the moment someone tries to use it, which for this specific kind of credential is the difference between stopping an incident before it reaches users and discovering it only after a compromised package has already shipped.
Talk to the Tracebit team to see how this applies to your environment.
FAQ
- Why is a stolen publish token specifically dangerous, compared to other credential theft?
- Because it doesn't just grant access to one company's systems, it grants the ability to publish new versions of a package under a maintainer's trusted identity, reaching every downstream consumer of that package. A single stolen token behind a widely used package can turn into a supply chain incident affecting thousands of organizations that never interacted with the original victim directly.
- How do publish tokens typically get stolen?
- Phishing targeting maintainers directly, credential stuffing against reused passwords, malware harvesting tokens cached locally on a maintainer's machine, or a compromised CI/CD pipeline that has publish access configured into it. Real incidents, including the Shai-Hulud campaign and the ua-parser-js compromise, have used variations of all of these.
- Where should a decoy publish token actually be placed?
- Wherever real publish credentials sit: a maintainer's local npm or PyPI configuration, a CI/CD pipeline's secrets used for automated releases, a password manager entry alongside the real token. It needs a plausible-looking scope and format for that registry so it isn't obviously distinguishable from a real one sitting next to it.
- Does 2FA on the registry account make this unnecessary?
- 2FA meaningfully raises the bar for account takeover, and every maintainer publishing a widely used package should have it enabled. It doesn't help once a long-lived publish token itself has already been issued and then stolen separately from the account login, which is exactly the scenario a decoy token is built to catch.