All npm classic tokens have been permanently revoked. They cannot authenticate, cannot be recreated, and cannot be recovered. The migration deadline passed on 19 November 2025, and what followed was not a grace period — it was deletion.
For most teams this registered as an annoying CI breakage in a sprint that had other plans. Then 4 August 2026 happened, and a worm propagated across 444 npm package names by harvesting publish tokens and republishing with them.
That is precisely the attack the token changes were designed to make impossible. Worth revisiting what actually changed and what it is worth.
What replaced classic tokens
Granular access tokens are scoped to specific packages or organisations, expire in a maximum of 90 days, and require 2FA by default. Compare that to a classic token: unscoped, non-expiring, valid for every package the account could publish.
Session-based npm login now issues a two-hour session token instead of a long-lived credential. Interactive publishing requires reauthentication after that window.
Trusted publishing via OIDC lets CI publish without any stored credential at all. The workflow presents a short-lived OIDC identity token; npm verifies it against a configured trust relationship and issues publish rights for that run. Nothing durable is stored anywhere. This implements the OpenSSF trusted publishers standard, already adopted by PyPI, RubyGems, and others.
2FA is moving to FIDO, with TOTP being deprecated — closing the phishing path that made TOTP a partial control.
Why trusted publishing specifically defeats worm propagation
Look at how the keyv payload spread. It harvested an npm token from an environment, then used that token to republish trojanized versions of every other package it could reach. Propagation was a direct function of standing credentials with broad scope.
Against trusted publishing, that step fails:
- There is no token in the environment to harvest. The credential is minted per-run and expires with the job.
- The credential is bound to a specific workflow in a specific repository. It cannot publish arbitrary packages.
- The publish is attributable to a workflow run, so anomalous publishes have provenance to check.
That does not make you invulnerable. An attacker who compromises the repository or the workflow definition can still publish through the trusted path. But it converts "steal one token, publish anywhere" into "compromise each repository individually" — which is the difference between a worm and a series of separate intrusions.
Our earlier analysis found that only a small fraction of compromised packages had trusted publishing configured. That number is the gap the ecosystem is still living in.
What actually breaks, and how to fix it
The migration is straightforward in principle and reliably annoying in practice. The recurring failures:
CI publishes fail with authentication errors. The stored NPM_TOKEN secret is now a revoked string. Configure trusted publishing for the repository and workflow, then remove the secret entirely rather than replacing it — a leftover secret is a liability with no remaining function.
Publishing from an unsupported CI provider. Trusted publishing requires OIDC support from the CI platform. GitHub Actions and GitLab CI are well covered; other providers vary. Where OIDC is unavailable, granular tokens with tight scope and 90-day rotation are the fallback — with a calendar entry, because the expiry will otherwise surprise you.
Local publishing scripts stop working unattended. A two-hour session token is incompatible with a cron job on someone's server. That workflow needs to move into CI, which is where it belonged.
Monorepo and multi-package publishing. Bulk trusted publishing configuration became generally available in February 2026, which removes the per-package configuration slog that made this painful for large repositories.
Permission scope surprises. Trusted publisher configurations created before 20 May 2026 default to allowing npm publish only. Configurations created after that date require explicitly selecting at least one allowed action. If a config predates the change and you now need other actions, it needs updating.
The migration you should do next
Getting publishing working again is the minimum. Two follow-ups are worth doing while the context is fresh:
Audit which packages you can still publish. Account takeover is the dominant supply chain attack vector right now — keyv, Mastra, and Nx were all maintainer-account compromises rather than software vulnerabilities. The publish rights held by dormant accounts and former contributors are the exposure. Remove what is not needed.
Apply the same reasoning everywhere else. npm forced this change; nobody is forcing it for your cloud credentials, your container registry, your artefact store, or your deployment keys. If a long-lived token sits in CI secrets for any of those, it has the same properties that made classic tokens worth deleting. The registries moved first because they got attacked first.
How Safeguard helps
Credential inventory across the publishing surface. Safeguard tracks which registries, repositories, and pipelines hold which credential types, so standing long-lived tokens are visible as a class rather than discovered during an incident.
Publish-provenance verification. Safeguard checks whether the packages you depend on were published through trusted publishing with attestations, so provenance becomes a signal in dependency selection instead of an invisible property.
Pipeline configuration policy. Safeguard validates that the controls you believe are in place — trusted publishing configured, no residual publish secrets, script execution settings, lockfile integrity — match what your pipelines actually run.
Lion for everything npm did not force. Lion enforces just-in-time secret brokering across build and agent environments, so cloud, registry, and deployment credentials are minted per-run and scoped per-capability, with egress allowlists and signed audit trails. It generalises the trusted-publishing model to the credentials no registry is going to revoke on your behalf.
Griffin for the migration work. Removing NPM_TOKEN references, updating workflow permissions, and configuring trusted publishing across dozens or hundreds of repositories is mechanical and tedious. Griffin authors and tests those changes as reviewable pull requests in parallel.
If your CI still stores a long-lived publish token for any registry, you are running the configuration the keyv worm was built to exploit. Deleting it is a Tuesday's work.
Sources: GitHub Changelog — npm classic tokens revoked · npm Docs — Trusted publishing · GitHub Changelog — bulk trusted publishing GA · GitHub — Our plan for a more secure npm supply chain · Aikido — keyv compromise