SlugFest: How a Repo Rename Could Hand Your npm Package to an Attacker
If you maintain an npm package that uses trusted publishing, this one is worth ten minutes of your time. A flaw in how npm identified your repository meant someone else could have published as you, without stealing a single credential.
Here is what The Hacker News reported about the flaw and GitHub’s response, followed by my take on what to do about it.
What was reported
Trusted publishing arrived in npm in July 2025. It lets you publish from a CI/CD platform like GitHub Actions using OpenID Connect (OIDC) tokens instead of long-lived npm secrets. The CI/CD provider generates a short-lived cryptographic token for a specific workflow run, and the npm registry verifies it against a pre-authorized configuration. That removes the need to store, rotate, or manually manage long-lived secrets. It also generates provenance attestations, so consumers can see where a package was built and who published it.
Bloom Security found a gap in how that configuration identified the repository. According to the article, npm recorded the repository’s slug (the owner/repository string) rather than the permanent numeric ID GitHub assigns, at least until a version is first published from that repository. GitHub’s OIDC tokens carry the numeric ID, which survives renames and transfers, but npm ignored it until that first successful publish.
Researcher Golan Myers put it this way: it’s like 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.
Bloom Security says the loophole could be used to take over thousands of packages and trigger a Shai-Hulud-style cascading supply chain attack.
The attack, called SlugFest
The precondition is narrow. The victim’s trusted publisher has to point to a GitHub slug an attacker can claim, and the package must never have been published from that repository. That happens when a maintainer renames, transfers, or deletes a repository and leaves the trust binding behind. Per the source, the steps are:
- Create a repository at the freed slug, which makes GitHub issue a fresh repository ID.
- Create and trigger an npm publish workflow, which mints an OIDC token carrying the reclaimed slug and the new numeric ID.
- Submit the token to npm’s exchange endpoint. npm sees the slug matches the stored one and issues a publish credential.
- Use the time-limited token to push malicious changes to a package the attacker doesn’t own.
The malicious version ships under the legitimate package name and inherits its reputation, download counts, and dependent relationships. Bloom Security reported finding over 1,500 vulnerable packages with more than 10 million combined downloads. The findings were reported to GitHub on June 6, 2026.
Myers noted the attack needs no insider knowledge, no credential theft, and no race condition. The only requirement is slug availability on a binding that hasn’t yet been used to publish, which he says is entirely a function of the victim’s own repository hygiene.
AI agents make it worse
Bloom Security also pointed to AI agents on developer machines. In their words, agents resolve dependencies on their own, tend to take the latest version, and rarely check where a package came from. A malicious version published through a reclaimed slug can get pulled in and run with no human in the loop.
Myers sketched a chain reaction. An attacker compromises a single package. An AI agent on a popular maintainer’s device pulls it autonomously. That one endpoint is then used to push malicious code to the popular package, and all of its users are exposed. One person with the right access got exposed, and the damage cascades from there.
What GitHub changed
GitHub now expires unvalidated trusted publishing configurations 48 hours after creation. A configuration becomes validated, and exempt from expiry, after its first successful publish, which binds it to the repository’s immutable identity. Changing the repository or project identity requires a new trust relationship with a fresh 48-hour validation window. Ordinary edits don’t restart the deadline. GitHub says this contains the risk of trusting a repository or project name that changes ownership.
npm will also reject trusted publishing tokens from GitHub Actions issue_comment events, alongside the existing pull_request_target restriction.
My take
The pattern here is old and keeps biting us. A human-readable name gets treated as if it were an identity. Names are reusable. IDs aren’t. Myers’ line in the article sums it up well: the binding between a readable identifier and the thing it identifies is the most important invariant in a trust system, and when it can be silently replaced by something as ordinary as a rename, the guarantee collapses.
Two things stand out to me.
First, the dangerous window is the gap between “I set up trusted publishing” and “I published once.” GitHub’s 48-hour expiry shrinks that window for new configurations. That’s a sensible fix. But the source describes the expiry in terms of newly created configurations, so I wouldn’t assume your older, never-used bindings are cleaned up for you. Check them.
Second, this wasn’t a one-off. The article notes that Bloom Security found a similar class of problem earlier this August, called “Extension Resurrection.” Open VSX and Microsoft’s VS Code Marketplace allowed extension packs to reference non-existent extensions. Attackers could claim the empty namespace, publish malicious code under it, and have it installed automatically alongside the trusted pack, pushing updates to anyone who had installed the pack. Myers pointed out that extensions run with full host access, so this effectively amounts to remote code execution delivered under the guise of legitimacy. The source counts as many as 87 vulnerable packs in Open VSX and 677 in the VS Code Marketplace. Different ecosystem, same mistake: an abandoned name that someone else can pick up.
What to do this week
The source gives maintainers a clear list. Here it is, with my notes:
- Audit your trusted publisher bindings. For each package, confirm the listed repository slug still resolves to a repository you control.
- Fix renamed or transferred repos. Delete the existing trust binding and re-create it pointing at the current slug.
- Monitor for unexpected publish events. If a version shows up that you didn’t ship, treat it as an incident.
- Make binding cleanup part of repo lifecycle. Delete trust bindings whenever you delete, transfer, or rename a repository. I’d add this to whatever checklist you already use for archiving or moving repos.
My own additions, which are suggestions and not from the article:
- If you set up trusted publishing but never completed a first publish, either publish or remove the binding. A binding that sits unused is exactly the case the attack needs.
- If you consume packages, especially through automated agents, pin versions and review updates to dependencies that matter. Agents grabbing the latest version by default is a risk you can reduce with a lockfile and a short allowlist.
The good news is the fix on GitHub’s side is in place and the cleanup on yours is small. The bad news is that a stale binding is easy to forget, and attackers only need one.
Sources
- GitHub Tightens npm Publishing After Flaw Left 1,500+ Packages Vulnerable to Hijacking — The Hacker News, 2026-10-13