Dead Maintainers, Hijacked Packages
The security community calls it namespace recycling — an adversary claims an abandoned package name, username, or domain after its original owner dies, burns out, or walks away. Every project that depended on the original namespace now silently pulls from the attacker.
But the same outcomes happen through simple neglect. The attacker doesn't always need to be clever. Sometimes they just need to be patient.
event-stream: The Canonical Handoff (npm, 2018)
Dominic Tarr maintained event-stream, a Node.js streaming library with 2 million weekly downloads. He'd moved on. When a stranger named "right9ctrl" offered to take over maintenance, Tarr said yes — because nobody else had asked.
Between September and November 2018, the new maintainer added a dependency called flatmap-stream containing an encrypted backdoor. The payload targeted Copay, a Bitcoin wallet, searching for balances over 100 BTC and exfiltrating wallet keys to a server in Kuala Lumpur.
A developer named Ayrton Sparling noticed a build warning and traced it back. By then the malicious code had been live for weeks.
Tarr's response was disarmingly honest: he'd mass-handed off the package because he no longer used it. There was no governance structure. No vetting process. Just one burned-out developer happy to give the keys to anyone who asked.
Sources: npm post-mortem · Snyk analysis · Academic paper
ua-parser-js: Single Point of Failure (npm, 2021)
On October 22, 2021, an attacker hijacked the npm account of Faisal Salman — the sole maintainer of ua-parser-js. They published three malicious versions containing a cryptominer (Linux and Windows) and DanaBot, a credential-stealing trojan targeting browsers, email clients, and VPNs.
The package had 7 million weekly downloads. Its dependents included Facebook (fbjs), Microsoft, Amazon, Google, Slack, Mozilla, Discord, and Reddit.
Salman noticed the compromise when his email got flooded with spam — a side effect of the account takeover. The malicious versions were live long enough to matter.
One person. One account. Seven million weekly downloads. No co-maintainers. No succession plan. No governance.
Sources: Sonatype · CrowdStrike
GitHub RepoJacking: 9 Million Repos at Risk (2023)
When a GitHub user renames their account, the old username becomes available. GitHub sets up a redirect — but if someone registers the old username and recreates the repo, the redirect breaks. Every go get, GitHub Action, or git clone pointing at the old URL now pulls from the attacker's repo.
Aqua Security's Nautilus team analyzed 1.25 million repositories and found 2.95% were vulnerable — extrapolating to roughly 9 million of GitHub's 300+ million repos. They found exploitable cases in repos managed by Google and Lyft.
GitHub's defense — "Popular Repository Namespace Retirement" — blocks re-registration of repo names with over 100 clones. It's been bypassed at least four times through race conditions, deletion/restoration tricks, and repository transfers. And it only protects popular repos. The long tail is wide open.
Sources: Aqua Security research · Checkmarx bypass · Snyk overview
PyPI Revival Hijack: 22,000 Orphaned Packages (2024)
PyPI allows immediate re-registration of deleted package names. JFrog discovered that roughly 22,000 removed packages — and an estimated 120,000 total deleted packages — could be hijacked by anyone willing to register the name.
This wasn't theoretical. An attacker going by "Jinnis" hijacked the package pingdomv3 on March 30, 2024 — the same day the original owner deleted it — and introduced a Base64-obfuscated payload.
JFrog's response was creative and grim: they created a security_holding PyPI account and defensively hijacked the most at-risk packages themselves, replacing them with empty placeholders. Those placeholders received 200,000+ downloads within days — proof that deleted packages aren't forgotten by the dependency graphs that still reference them.
As of this writing, PyPI has been deliberating a policy change for over two years. Package names remain immediately reusable after deletion.
Sources: JFrog research · BleepingComputer
Domain Expiry: The Identity Layer Rots
Packages have maintainers. Maintainers have email addresses. Email addresses have domains. Domains expire.
Security researcher Matthew Bryant found that the npm account for ajv-formats (~5 million weekly installs, transitive dependency of Angular CLI) was registered to an email address at an expired domain. Buying that domain would give you password-reset access to the npm account. Angular CLI -> @angular-devkit/core -> ajv-formats -> you.
Security consultant Lance Vick took it further. He purchased the expired domain of the sole maintainer of the npm package foreach and now controlled the package and its 36,826 dependents. A broader scan revealed 2,818 maintainer email addresses at expired domains, controlling 8,494 packages.
The problem isn't limited to package registries. Truffle Security found that Google's "Sign in with Google" doesn't prevent account takeover when a domain changes ownership. They identified 116,481 defunct startup domains currently for sale, with roughly 10 million accounts at risk across Slack, ChatGPT, Zoom, and HR platforms. Buying a dead startup's domain lets you re-create employee emails and walk into every SaaS product those employees ever used.
Domains don't just expire when people die. But when people die, domains always expire.
WordPress: The Plugin Graveyard (2017-2024)
WordPress.org has an explicit policy of allowing "abandoned" plugins to be adopted by new maintainers. In 2017, the owner of Display Widgets (200,000+ active installations) sold the plugin to a buyer for $15,000. The buyer immediately began inserting backdoors that published spam and collected visitor data. The plugin was removed from WordPress.org three times. The buyer kept resubmitting modified versions.
In June 2024, an attacker compromised five WordPress.org developer accounts using credentials from prior data breaches, then committed malicious code to their plugins. The payload created rogue admin accounts and injected cryptominers, delivered to every site that auto-updated.
Meanwhile, W3 Total Cache — one of the most-installed caching plugins with 1M+ active installations — went three years without a single update despite critical security flaws. The developer became non-responsive. WordPress.org repeatedly denied community takeover requests. The plugin remained downloadable the entire time.
colors.js: When the Maintainer Is the Threat (2022)
Not every succession failure involves death or disappearance. Sometimes the maintainer is alive, furious, and still has the keys.
In January 2022, Marak Squires — sole maintainer of colors.js (3.3 billion lifetime downloads, 19,000+ dependents) and faker.js (272 million lifetime downloads) — intentionally sabotaged both packages. He introduced an infinite loop in colors.js and purged all functional code from faker.js, publishing it as version 6.6.6.
His motivation: "No one pays for Faker development... I also can't afford to work for free."
The project depends on a single person's goodwill. Without governance structures, the single maintainer is a single point of failure whether they leave, die, get hacked, or go rogue.
The Numbers Behind the Neglect
These aren't isolated incidents. They're symptoms of a structural problem.
| Metric | Number | Source |
|---|---|---|
| GitHub repos vulnerable to RepoJacking | ~9 million | Aqua Security, 2023 |
| PyPI packages vulnerable to Revival Hijack | 22,000+ | JFrog, 2024 |
| npm packages at risk via expired maintainer email domains | 8,494 | The Record, 2022 |
| Defunct startup domains for sale (OAuth attack surface) | 116,481 | Truffle Security, 2025 |
| Open source maintainers who experienced burnout | 46-73% | Tidelift / community surveys |
| Maintainers who are unpaid | 60% | byteiota |
| Repos with any form of sponsorship | 1.3% | OpenSauced |
The Missing Layer
Platforms are building better locks. Mandatory 2FA. Sigstore provenance. Trusted publishers. These are good things — but they solve the wrong problem. 2FA keeps attackers out. It also locks out legitimate successors when the maintainer dies and their authenticator app goes with them. Sigstore proves who published a package, not whether they should still be the one publishing it. Trusted Publishers bind packages to CI pipelines, but when a maintainer disappears, the CI stops running and the package fossilizes.
Nobody is planning for what happens when the locksmith dies.
A succession protocol could change this. If a maintainer could cryptographically declare "when I die, transfer publishing rights to this person" — and platforms could verify that declaration against a threshold death attestation — then namespace recycling attacks would lose their attack surface entirely. Dead maintainers wouldn't create abandoned namespaces. They'd create orderly transitions.
That's what RFC 0xDEAD is trying to sketch out.