If your npm account was used to publish something you did not publish, lock the account first, then warn users, then remove or deprecate the bad versions, then fix how you publish. Unpublishing may not be allowed, so plan to use deprecation and a clean new version.
Step 1: stop further damage
Change your password from a clean device, revoke every access token, and reset your two factor setup. Check the account for new tokens, new maintainers added to your packages, and changed email addresses. Do the same on your source hosting account and on any CI system that holds publish credentials. An attacker who has one often has the other.
Revoke tokens even if you think only one leaked. You can create new ones later.
Step 2: warn people quickly
A short, factual notice beats a perfect one. Say which versions are bad, the time range, what they do if you know, and what users should do. Put it where users look: the repository, the package readme, and your security advisory channel.
Do not guess at impact. If you do not yet know what the malicious code does, say that and tell users to treat environments that installed it as exposed.
Step 3: remove or deprecate
npm's unpublish policy limits what you can remove:
- Within 72 hours of publishing, you can unpublish as long as no other public packages depend on it.
- After 72 hours, you can unpublish only if no public package depends on it, it had fewer than 300 downloads in the last week, and it has a single owner or maintainer.
- Unpublished version numbers can never be reused, and unpublishing cannot be undone.
If the package does not qualify, npm recommends deprecation. A deprecated version stays downloadable but shows a warning message on install. The command takes a package and version plus a message, so write a message that says plainly not to use that version. If you need help, contact npm support, which the policy page names as the route when an eligible unpublish fails.
Be clear in your message that deprecation is a warning, not a removal. Users who pinned the bad version will still install it, with a notice.
Step 4: publish a clean version
Publish a new version from a verified clean source. Check the diff against the last good version, including install scripts and bundled files. Use a new version number, since the bad numbers cannot return. Say in the advisory which version is safe.
Step 5: remove long lived publish tokens
npm trusted publishing lets a CI workflow publish using OpenID Connect and short lived, signed tokens tied to that workflow, so there is no persistent write token to leak. It needs a recent npm CLI and Node, cloud hosted runners, and matching publisher details on the registry. Self hosted runners are not supported, and a new configuration must complete its first publish within two days. Check the current npm documentation for the version numbers before you plan.
Also require two factor authentication for publishing, and keep the maintainer list short and reviewed.
Step 6: review and learn
Write a blameless review: how the credential was taken, how long before anyone noticed, what limited the damage. For the format, see the blameless postmortem template.
Where a gate can help downstream
Teams that consume your package can use policies and gates, such as those in Safeguard, to hold new versions for review before they enter a build. That does not replace your own account hygiene, but it narrows how far a bad release spreads.
Quick check
Can I always unpublish a malicious version?
No. npm allows it within 72 hours if nothing public depends on it, and after that only under tighter conditions. Otherwise deprecate.
Can I reuse the version number after unpublishing?
No. npm says unpublished version numbers can never be reused.
Sources
Last reviewed: 19 October 2026.