Skip to main contentClaim $5 in free credit — one-time, per account. Claim $5 free
Krova CloudKrova Cloud
AI Code Sandboxing

SlugFest: npm Trusted Publishing Trusted Names, Not IDs

npm bound publishing trust to a repository name, not its immutable ID. Claiming a freed slug was enough to publish, and 1,500+ packages sat exposed.

7 min read
Share
SlugFest npm trusted publishing slug reclaim illustration

SlugFest: npm Trusted Publishing Trusted Names, Not IDs

SlugFest is the npm Trusted Publishing flaw Bloom Security disclosed on 13 October 2026. Publishing trust was bound to a GitHub owner/repo slug instead of the immutable repository ID, so anyone who claimed a freed name could publish new versions carrying valid provenance. Bloom counted more than 1,500 exposed packages with over 10 million downloads. The fix shipped on 2 October; the audit is still yours.

A lock that checks the door, not the owner

npm's Trusted Publishing, generally available since July 2025, replaces long-lived publishing tokens. A maintainer tells npm which GitHub repository and workflow file may publish; the workflow receives a signed OIDC identity token, and npm exchanges it for a publish credential that expires within minutes.

The binding npm recorded, per Bloom's disclosure: the owner/repo slug, the workflow file name, and an optional environment. Every GitHub OIDC token also carries repository_id and repository_owner_id, permanent numbers that survive renames and transfers, but until a first publish npm had nothing to compare them against. Bloom's metaphor: a lock that checks the address on the door rather than who owns the house. When the owner moves out, whoever moves in gets the key.

The four-step attack, no credentials

The precondition is a trusted-publisher binding that points at a slug an attacker can claim and has never been used to publish. Renaming, transferring or deleting the bound repository frees the slug, and so does renaming or deleting the owner account. From there, per Bloom and The Hacker News' reconstruction, the attack is mechanical:

  1. Create a repository at the freed slug; GitHub issues it a fresh numeric ID.
  2. Add a workflow whose file name matches the binding, with id-token: write permission.
  3. Run it, minting an OIDC token whose repository claim carries the old slug.
  4. Submit the token to npm's exchange endpoint; slug and file name match, and npm issues a publish credential.

No token theft, no account takeover, no malware required. The release even carries a valid provenance attestation naming the attacker's repository. In our ChainDrop runbook the provenance was valid because the workflow was hijacked; here it is valid because the name was.

What the 48-hour fix closes, and what it leaves

Bloom reported the flaw through GitHub's HackerOne program on 6 June 2026; the report was validated on 9 June, and the fix shipped on 2 October, more than 120 days later, per Bloom's timeline and Help Net Security. Unvalidated Trusted Publishing configurations now expire 48 hours after creation and can no longer authorise publishing.

The first successful publish validates a configuration and binds it to the repository's immutable identity, and changing repository or project identity requires a fresh trust relationship with a new 48-hour window. npm also rejects tokens minted by issue_comment events, joining the existing pull_request_target block, so maintainers should move publishing to push, release or workflow_dispatch triggers.

What the fix leaves behind is operational. Organisations keep renaming and deleting repositories, and every such change recreates the condition: a binding that must publish within two days or die. The flaw is closed; the habit that exposed it is not.

Agents turned a slow flaw into an urgent one

Bloom said it caught and blocked its own customers' AI agents attempting to download some of the exposed packages. Agents resolve dependencies on their own, tend to take the latest version, and rarely check where a package came from, per the disclosure, so a malicious version published through a reclaimed slug gets pulled in and runs with no human in the loop.

Our rogue agents record keeps showing the same shape: machines act faster than governance catches up. And gitspawn showed the git-side variant of trusting a name that anyone can occupy.

The trusted-publishing audit

  1. Inventory every trusted-publisher configuration your organisation owns, including scoped and org-owned package names.
  2. Confirm each configuration has completed at least one successful publish, because that first publish is what binds the immutable repository ID.
  3. Recreate any stale, never-published configuration inside a controlled 48-hour window and publish immediately from the real repository.
  4. Check trigger events: publishing workflows on issue_comment or pull_request_target must move to push, release or workflow_dispatch.
  5. Treat slug-freeing events as change control: repository renames, transfers, deletions and owner-account changes should trigger a binding review.
  6. Monitor provenance rather than validity: alert when an attestation names a repository nobody recognises, and treat unexpected versions of dormant packages as incidents, the same behaviour-over-names posture our MALFEX breakdown argues from the other direction.

Verdict, and the caveats on this page

Our verdict: SlugFest is the cleanest example yet of a trust model failing at identity. Names are leases, IDs are ownership, and the fix binds ownership at first publish. The residue is every binding that has never published and every rename that happens without a review.

  • The 1,500+ packages are potentially exposed, not confirmed compromised; Bloom demonstrated the takeover end to end only on packages its researchers controlled, which is a limitation of ethical research, not proof of restraint in the wild.
  • No public exploitation has been confirmed, so this is a takeover path rather than an active campaign; however, paths and campaigns are separated only by timing.
  • The fix details come from GitHub's changelog and npm documentation as reported by Bloom, THN and Help Net Security, and we cannot verify registry server behaviour from outside.
  • In our Linux microVM fleet the sandbox limits what a poisoned install can reach, but it does not prevent the poisoning, since npm trust decisions happen at organisation level.

FAQ

Is SlugFest still exploitable?

Not in its original form. Since 2 October 2026, unvalidated Trusted Publishing configurations expire 48 hours after creation, and the first successful publish binds the repository's immutable ID, so a reclaimed slug no longer matches. The residual risk is operational: a never-published binding, or a fresh binding created after an identity change, reopens a two-day window if nobody publishes inside it.

Does valid provenance protect me from attacks like SlugFest?

No. An attacker's release carries a perfectly valid provenance attestation that names the attacker's own repository. Provenance proves where a build ran, not that it ran where you intended. Read the repository identity inside the attestation, not just its validity, and pin dependency versions instead of resolving to latest.

What should maintainers do this week?

Three things. Confirm each package's trusted publisher has completed at least one successful publish, so the immutable ID is bound. Move any publishing workflow off issue_comment and pull_request_target triggers. Add a review step to repository renames, transfers and deletions, so no routine cleanup silently frees a slug that a binding still trusts.

{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "BlogPosting",
      "headline": "SlugFest: npm Trusted Publishing Trusted Names, Not IDs",
      "datePublished": "2026-10-20",
      "dateModified": "2026-10-20",
      "author": {"@type": "Organization", "name": "Krova Cloud Engineering"},
      "publisher": {"@type": "Organization", "name": "Krova Cloud"},
      "mainEntityOfPage": "https://krova.cloud/blog/slugfest-npm-trusted-publishing-slug-reclaim"
    },
    {
      "@type": "FAQPage",
      "mainEntity": [
        {
          "@type": "Question",
          "name": "Is SlugFest still exploitable?",
          "acceptedAnswer": {"@type": "Answer", "text": "Not in its original form. Since 2 October 2026, unvalidated Trusted Publishing configurations expire 48 hours after creation, and the first successful publish binds the repository's immutable ID, so a reclaimed slug no longer matches. The residual risk is operational: a never-published binding, or a fresh binding created after an identity change, reopens a two-day window if nobody publishes inside it."}
        },
        {
          "@type": "Question",
          "name": "Does valid provenance protect me from attacks like SlugFest?",
          "acceptedAnswer": {"@type": "Answer", "text": "No. An attacker's release carries a perfectly valid provenance attestation that names the attacker's own repository. Provenance proves where a build ran, not that it ran where you intended. Read the repository identity inside the attestation, not just its validity, and pin dependency versions instead of resolving to latest."}
        },
        {
          "@type": "Question",
          "name": "What should maintainers do this week?",
          "acceptedAnswer": {"@type": "Answer", "text": "Three things. Confirm each package's trusted publisher has completed at least one successful publish, so the immutable ID is bound. Move any publishing workflow off issue_comment and pull_request_target triggers. Add a review step to repository renames, transfers and deletions, so no routine cleanup silently frees a slug that a binding still trusts."}
        }
      ]
    }
  ]
}
For AI agents:llms.txtsitemap

Related posts