Safeguard
Supply Chain Security•

npm Trusted Publishing Now Expires Unused Configs After 48 Hours

npm matched never-used trusted publishing configs by repository name, so a reclaimed repo name could publish your package. Unvalidated configs now expire after 48 hours.

Safeguard Security Team
5 min read

On 2 October 2026, npm changed trusted publishing so that a configuration which has never been used to publish expires 48 hours after it is created. The same change stops npm from accepting trusted publishing tokens minted in GitHub Actions issue_comment workflows. On 13 October, Bloom Security published the research behind it, which it calls SlugFest: until a configuration's first publish, npm matched the trusted repository by its owner/repo name, so whoever claimed that name could publish your package.

What's affected

Trusted publishing lets a CI workflow exchange a short-lived OIDC token for permission to publish, with no long-lived npm token. Bloom's write-up explains that a trusted publisher binding stores the repository slug, the workflow filename and an optional environment. GitHub's OIDC token also carries the numeric repository_id and repository_owner_id, which survive renames and transfers. Per Bloom, npm only records those IDs after the first successful publish. Before that, it had nothing to compare them against.

That opens a window when all of these are true:

  • A package has a trusted publisher configured.
  • That configuration has never published a version.
  • The named repository or owner was renamed, transferred or deleted, so the old name can be registered by someone else.

An attacker registers the freed name, adds a workflow with the matching filename, and exchanges the resulting token for a publish credential. No maintainer account is touched. Bloom says it found more than 1,500 packages in this state, with more than 10 million combined downloads, and is not publishing the list. Bloom also says the issue affected npm's GitLab trusted publishing. It reported the flaw to GitHub on 6 June 2026. Neither Bloom nor GitHub reported exploitation in the wild.

GitHub's 2 October changelog describes the fix:

  • An unvalidated configuration expires 48 hours after creation and can no longer authorize publishing.
  • A configuration becomes validated, and exempt from expiry, after its first successful publish.
  • Changing the repository or project identity needs a new trust relationship with a fresh 48-hour window.
  • Expired configurations stay visible in settings and can be recreated.
  • npm now rejects trusted publishing tokens from issue_comment events, alongside the existing block on pull_request_target.

How to check if you're exposed

List the trust configuration for each package you maintain. The npm trust command needs npm 11.15.0 or later:

npm --version
npm trust list your-package --json

For each GitHub binding, confirm the repository still exists at that exact name and belongs to you. A rename leaves a redirect, which hides the problem when you browse to it, so check the API's canonical name:

gh api repos/OWNER/REPO --jq '.full_name, .id, .owner.login'

If the returned full_name differs from the slug in your binding, or the call returns 404, the binding points at a name someone else can claim.

Then check your publishing workflows for the event that is now refused:

grep -rnE 'issue_comment|pull_request_target' .github/workflows/

Any workflow that publishes from either trigger will fail. Neither belongs in a release path, because both can run in response to people outside your team.

What to do now

  1. Publish soon after you create a binding. A configuration you create and then leave idle for two days now expires. Create it in the same session as the first release.

  2. Fix bindings that point at old names. Revoke the stale configuration and create a new one against the current repository:

    npm trust list your-package
    npm trust revoke your-package --id=TRUST_ID
    npm trust github your-package --repo your-org/your-repo --file release.yml --allow-publish
    
  3. Revoke bindings before deleting or transferring a repository. Bloom's advice is to treat the trust binding as part of the repository's lifecycle.

  4. Move publishing to allowed events. GitHub lists push, release and workflow_dispatch. Pair them with a protected environment that requires approval.

  5. Watch for publishes you didn't make. Compare npm's version times against your release workflow runs. A version with no matching run is an incident.

Why it matters

Trusted publishing is the right direction, and this flaw doesn't change that. It removes the long-lived npm token that so many 2026 incidents started with. But it moves trust onto an identifier, and names are not identities. Any system that trusts owner/repo without the numeric ID inherits GitHub's rename and reuse rules.

The same lesson applies to anything you configure by name: OIDC trust policies in cloud accounts, workflow references, Go module paths. Check that you pin the immutable identifier where the platform offers one, and clean up trust when the thing you trusted goes away.

Try it yourself

Pick one npm package your team publishes. Run npm trust list on it, resolve the repository with gh api, and look at the last ten versions on the registry. Can you match every version to a workflow run in that repository? If not, write down which step of your release process would have caught a publish from somewhere else.

Click through it at your own pace, or open it full screen.

Quick check

Which trusted publishing configurations were exposed to SlugFest?

Configurations that had never been used to publish, and whose named repository or owner had been renamed, transferred or deleted so the old name could be claimed.

What happens to a configuration you create but don't use for three days?

It expires after 48 hours and can no longer authorize publishing. You can recreate it to start a new 48-hour window.

Which GitHub Actions events can no longer mint npm trusted publishing tokens?

issue_comment and pull_request_target. Use push, release or workflow_dispatch instead.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.