TrapDoor: 34 packages went bad overnight — and a 3-day rule would have stopped them

In late May 2026, security researchers disclosed a supply-chain campaign that came to be known as TrapDoor. More than 34 malicious packages went up across PyPI, npm and Crates.io at roughly the same time. They were not broken or buggy — they were built to run hostile code the moment they were installed or imported, scraping SSH keys and credentials off the machine and sending them to the attackers (reported by The Hacker News, 25 May 2026).

If you have wondered why the 5bats tools exist, this is the short answer. TrapDoor is the attack the toolset was built in response to — and the uncomfortable part is how ordinary it was. No zero-day, no clever exploit. Just packages, published normally, that a normal install command pulled straight onto developers’ machines.

What made it slip through

Here is the detail that matters: when researchers caught it, every one of the malicious PyPI packages was less than 72 hours old. That is not a coincidence — it is the whole strategy. A brand-new release lives in a blind spot. The security databases that tools check against have not seen it yet, so there is no CVE, no advisory, nothing to flag. By the time the ecosystem catches up and pulls the package, it has already run on every machine that installed it in those first hours.

That is why the usual advice — “scan your dependencies for known vulnerabilities” — does not help here. There was nothing known to scan for. And post-install scanners run after the package’s code has already executed, which for an attack that fires on install is far too late.

TrapDoor had a second trick worth noting: some payloads planted hidden instructions in CLAUDE.md and .cursorrules files — the configuration that steers AI coding assistants — turning the assistant itself into an accomplice on the next run. So it was both a supply-chain attack and a prompt-injection one.

What would have stopped it

This is the point of a recap like this — not to alarm, but to show that the defence is unglamorous and effective.

  • A freshness hold. pip-cve-gate refuses, by default, to install any release younger than three days. Against TrapDoor that single rule is decisive: every malicious PyPI package was inside that window, so they would have been blocked outright — no CVE required, nothing to look up. The attack’s greatest strength, its newness, is exactly what a freshness hold turns into a weakness.
  • A pre-install check, not a post-install one. Because the gate runs before the install, the hostile code never gets its moment to execute. The same idea covers Composer and Homebrew, and — for the packages an AI assistant installs on your behalf — claude-code-cve-gate.
  • A line between reading and running. For the CLAUDE.md trick, claude-code-prompt-injection-gate locks the files an attacker would want to rewrite, so a poisoned package cannot quietly reprogram your assistant.

The takeaway

TrapDoor was not the first attack of its kind and it will not be the last — which is the real lesson. You cannot rely on being warned in time, because the most dangerous packages are the ones nobody has been warned about yet. A standing rule that simply waits a few days, and checks before it installs, does not need the warning. It is the difference between defending against the attacks already known and defending against the next one.

For the full explanation of how these attacks work, see the guide on software supply-chain attacks.

← Back to all posts