On May 22, 2026, at 20:20:18 UTC, a PyPI package called eth-security-auditor@0.1.0 went live. Its name was a lie. Within 72 hours, the supply-chain security firm Socket had connected it to a coordinated, cross-ecosystem campaign it named TrapDoor: more than 34 malicious packages spanning over 384 versions and artifacts published across npm, PyPI, and Crates.io. The packages did not target end users of any single application. They targeted the people who build crypto and DeFi software, plus the AI tooling those people increasingly trust to write and review their code.
TrapDoor lands in the middle of a brutal stretch for the crypto ecosystem. By the time Socket published its disclosure on May 24, 2026, the first four months of the year had already seen more than a billion dollars lost to DeFi exploits, including the KelpDAO bridge drain in April. But most of those losses came from on-chain smart-contract failures and key compromises. TrapDoor is a different and arguably more durable threat. It does not attack a contract. It attacks the developer's laptop, their CI/CD pipeline, their cloud account, and their wallet keystore, which means it sits upstream of every contract that developer will ever deploy.
What makes the campaign worth studying is not its scale, which is moderate, but its design. TrapDoor was built for a specific population of victims, it weaponized AI coding assistants as an exfiltration channel, and it spread across three package registries that most teams scan with three different and uncoordinated tools. This is what a modern, audience-targeted software supply-chain attack looks like, and the crypto industry happened to be first in line.
TL;DR
- Socket disclosed TrapDoor on May 24, 2026: a coordinated campaign of 34+ malicious packages and 384+ versions/artifacts across npm (21 packages), PyPI (7), and Crates.io (6).
- The earliest observed artifact was the PyPI package
eth-security-auditor@0.1.0, uploaded May 22, 2026 at 20:20:18 UTC. Packages were published in waves by a cluster of accounts and updated through the weekend. - Targets were developers in crypto, DeFi, Solana, and AI communities. Stolen data included crypto wallet keystores (Sui, Solana, Aptos, browser extension wallets), SSH keys, AWS credentials, GitHub tokens, browser profiles, and environment variables.
- Each ecosystem used a different execution trigger: npm
postinstallhooks runningtrap-core.js, PyPI import-time execution that pulled JavaScript from attacker GitHub Pages, and Crates.iobuild.rsscripts that XOR-encrypted keystores and exfiltrated to GitHub Gists. - A defining tactic: planting
.cursorrulesandCLAUDE.mdfiles with instructions hidden in zero-width Unicode characters to trick AI coding assistants into running credential discovery and exfiltration "as part of a security scan." - Socket reported a mean detection time of 5 minutes 56 seconds, fastest 58 seconds, but registry detection speed does not protect a developer who installs in that window.
- Monday-morning actions: audit recent installs against the named packages, rotate any keys and wallet secrets touched by affected machines, and treat AI assistant config files as executable supply-chain artifacts.
What happened
Socket's analysis, corroborated by The Hacker News and other outlets, describes a single threat actor operating across three registries with a shared payload design but ecosystem-specific delivery. The package names were chosen to blend into the workflows of their targets. They impersonated security tools, wallet utilities, and build helpers, the exact kind of dependency a crypto or DeFi developer would add without a second thought.
A representative sample of the named packages:
- npm:
async-pipeline-builder,crypto-credential-scanner,web3-secrets-detector,wallet-security-checker - PyPI:
cryptowallet-safety,eth-security-auditor,solidity-build-guard - Crates.io:
move-analyzer-build,sui-framework-helpers,sui-sdk-build-utils
The naming is the point. Several of these masquerade as the very security and auditing tooling a careful developer reaches for. eth-security-auditor, web3-secrets-detector, and wallet-security-checker sound like defensive utilities. Installing one to "scan for secrets" was the act that leaked them.
The packages were published in rapid waves from a handful of clustered accounts and actively updated across the weekend of May 22 to 24. Socket attached the campaign marker P-2024-001 to the operation and tied infrastructure back to a single GitHub account, ddjidd564, hosting payloads at ddjidd564[.]github[.]io.
How the attack worked
TrapDoor's authors clearly understood that npm, PyPI, and Crates.io each execute third-party code at a different point in the dependency lifecycle, and they tailored the trigger to each.
npm: postinstall execution
The npm packages relied on the oldest trick in the registry, the postinstall lifecycle hook, to run a shared JavaScript payload named trap-core.js (about 48 KB). The payload scanned the host for credentials and developer secrets, then validated what it found by calling live AWS and GitHub APIs to confirm the tokens were active before exfiltration. It established persistence through cron jobs, systemd services, Git hooks, and shell profile hooks, and attempted SSH-based lateral movement to other hosts the developer could reach.
The following is an illustrative sketch of the kind of manifest wiring involved. It is not functional exploit code.
// package.json — ILLUSTRATIVE, not the real payload
{
"name": "wallet-security-checker",
"version": "1.0.3",
"scripts": {
"postinstall": "node ./scripts/trap-core.js"
}
}
PyPI: import-time execution and a Node bridge
The Python packages executed on import rather than at install. On first import they reached out to an attacker-controlled GitHub Pages domain, downloaded JavaScript, and executed it through the locally installed Node runtime via node -e. This cross-language bridge let the actor reuse the same JavaScript stealer logic across the Python and npm packages, and it sidesteps defenders who only think of Python supply-chain risk in terms of Python code.
Crates.io: build.rs and XOR exfiltration
The Rust crates abused build.rs, the build script Cargo runs at compile time. The malicious build script searched the host for local keystores, encrypted what it found using a hardcoded XOR key (cargo-build-helper-2026), and exfiltrated the result to GitHub Gists. XOR with a static key is trivial to reverse, which tells you the goal was speed and low friction, not cryptographic secrecy.
The AI assistant channel
The most novel element of TrapDoor was its abuse of AI coding assistants. The packages planted or modified .cursorrules and CLAUDE.md files, the configuration and instruction files that tools like Cursor and Claude-based assistants read to understand a project. Inside those files, the actor embedded hidden instructions using zero-width Unicode characters, invisible in a normal editor view, that told the assistant to run credential discovery and exfiltration steps framed as a routine "automated project security scan."
This is a prompt-injection supply-chain hybrid. The developer never sees the instruction. The AI assistant reads it, treats it as a legitimate project directive, and the human, trusting the assistant, approves the resulting commands. Socket also reported the actor opened pull requests against high-profile AI repositories including browser-use/browser-use, langchain-ai/langchain, and langflow-ai/langflow, attempting to seed the poisoned instruction files into trusted projects.
What detection looks like
TrapDoor leaves signals at install time, at runtime, and in source control. None of them require exotic tooling.
Behavioral signals on developer and CI hosts:
- A package install or first import that spawns an outbound connection to
*.github.ioor creates a GitHub Gist. node -einvocations originating from a Python process or import.- New cron jobs, systemd unit files, Git hooks, or shell-profile edits appearing immediately after a dependency install.
- AWS STS or GitHub API calls from a developer workstation that has never made them before, especially token-validation calls in tight succession.
Hunting queries you can adapt to your EDR or audit logs:
# Illustrative detection logic, adapt to your tooling
# 1. Node executing inline script spawned by a Python process
parent_process IN ("python", "python3", "pip")
AND process_name == "node"
AND command_line CONTAINS "-e"
# 2. New persistence written within 60s of a package manager run
file_create IN ("~/.bashrc", "~/.zshrc", "/etc/systemd/system/*",
"crontab", ".git/hooks/*")
AND preceding_process IN ("npm", "pip", "cargo")
# 3. Outbound to known TrapDoor infra
dns_query == "ddjidd564.github.io"
OR http_host CONTAINS "github.io" AND user == <developer>
Source-control and content signals:
- Presence of zero-width Unicode characters (U+200B, U+200C, U+200D, U+FEFF) inside
.cursorrules,CLAUDE.md,AGENTS.md, or similar AI instruction files. A simple grep for non-printable codepoints in these files is worth adding to CI. - Unexpected additions or modifications of AI assistant config files in dependency PRs.
Known IOCs from the Socket disclosure: GitHub account ddjidd564, domain ddjidd564[.]github[.]io, the Crates.io XOR key string cargo-build-helper-2026, and the campaign marker P-2024-001.
What to do Monday morning
-
Inventory recent installs against the named packages. Search your lockfiles and CI logs across all three ecosystems for the published names (
eth-security-auditor,web3-secrets-detector,wallet-security-checker,crypto-credential-scanner,solidity-build-guard,sui-sdk-build-utils, and the others Socket lists). Do not rely on production manifests alone; developers install experimental packages locally that never reach a lockfile.# npm / yarn / pnpm grep -RinE "eth-security-auditor|web3-secrets-detector|wallet-security-checker|crypto-credential-scanner" \ package-lock.json yarn.lock pnpm-lock.yaml 2>/dev/null # Python pip list 2>/dev/null | grep -iE "cryptowallet-safety|eth-security-auditor|solidity-build-guard" # Rust grep -RinE "move-analyzer-build|sui-framework-helpers|sui-sdk-build-utils" Cargo.lock 2>/dev/null -
Treat any matched host as compromised. Rotate everything that machine could reach: SSH keys, AWS credentials, GitHub personal access tokens and OAuth tokens, and, critically, any crypto wallet keystores or seed phrases stored or unlocked on that host. Move funds from any hot wallet whose keys lived on an affected machine.
-
Hunt for persistence. Check for new cron entries, systemd units, Git hooks, and shell-profile modifications dated to the install window. Removing the package does not remove the implant.
-
Scan AI assistant config files for hidden instructions. Grep
.cursorrules,CLAUDE.md, and equivalents for zero-width Unicode codepoints and for any instruction referencing credential scanning, secret discovery, or exfiltration. Add this check to CI so poisoned files cannot be merged silently. -
Disable automatic install-time script execution where you can. Use
npm install --ignore-scriptsin CI by default and allowlist the packages that genuinely need lifecycle scripts. For Rust, build untrusted dependencies in a sandbox that denies network egress at compile time. -
Pin and review, do not blind-upgrade. TrapDoor pushed malicious updates to existing-looking package lines through the weekend. Pin exact versions and require human review on dependency bumps, especially for anything in your wallet, signing, or deployment path.
Why this keeps happening
TrapDoor succeeded not because it was technically advanced, the XOR key and the postinstall hook are decades old, but because it exploited two structural blind spots.
The first is ecosystem fragmentation. A typical crypto or DeFi shop ships JavaScript front-ends, Python tooling, and Rust on-chain code, and it scans each registry with a different tool, or no tool. An actor who publishes the same campaign across npm, PyPI, and Crates.io is betting, correctly, that no single dashboard sees the whole picture and that a package blocked on one registry is still live on another. Cross-ecosystem correlation is the gap, and TrapDoor was designed to live in it.
The second is the new and largely ungoverned trust we place in AI coding assistants. Config files like .cursorrules and CLAUDE.md are now executable in every meaningful sense: an assistant reads them and acts on them, often with the developer's standing approval to run commands. Yet most teams treat these files as documentation, exclude them from code review, and never scan them for hidden content. A zero-width Unicode payload in a project instruction file is the supply-chain equivalent of a malicious build script, and almost nobody is looking.
The structural fix
The honest framing is that nothing would have "prevented" a developer from installing a convincingly named package in the first minute it was live. What changes the outcome is how quickly the install is caught and how small the blast radius is.
Safeguard's reachability analysis and SBOM coverage span npm, PyPI, and Crates.io in one view, so a package that is blocked or flagged in one ecosystem is not silently trusted in another. Maintainer-takeover and typosquatting detection raise the bar on newly published, security-themed package names of exactly the type TrapDoor used. And because the campaign weaponized AI assistant config files, Safeguard's MCP and AI governance and prompt-injection defenses extend the same scrutiny to the instruction files and tool-calling paths that coding assistants act on, treating a poisoned CLAUDE.md as the supply-chain artifact it actually is. The goal is not a promise of prevention. It is shorter dwell time and a contained radius when, not if, the next TrapDoor lands.
What we know we don't know
- Attribution. Socket has not publicly tied TrapDoor to a named threat group. The
P-2024-001marker and the operational pattern suggest a deliberate, possibly reusable operation, but motive beyond credential and wallet theft is not established in the disclosure. - Confirmed losses. As of the disclosure, there is no public, verified dollar figure for crypto stolen via TrapDoor specifically. The campaign harvested wallet keystores and SSH/cloud credentials; downstream losses, if any, were not quantified.
- Total victim count. Download counts and the number of developers who executed a payload before removal are not fully public. Fast registry detection limited exposure but does not bound it.
- AI-assistant success rate. It is not publicly confirmed how often the zero-width instruction files actually caused an assistant to exfiltrate data versus being caught or ignored.
References
- Socket, "TrapDoor Crypto Stealer Supply Chain Attack Hits 34 Packages Across npm, PyPI, and Crates.io" — https://socket.dev/blog/trapdoor-crypto-stealer-npm-pypi-crates
- The Hacker News, "TrapDoor Supply Chain Attack Spreads Credential-Stealing Malware via npm, PyPI, and Crates.io" — https://thehackernews.com/2026/05/trapdoor-supply-chain-attack-spreads.html
- Cybersecurity News, "Hackers Compromised 34 Packages in npm, PyPI, and Crates in New Supply Chain Attack" — https://cybersecuritynews.com/supply-chain-trapdoor-malware/
- The Crypto Times, "TrapDoor Malware Hits npm, PyPI & Crates.io, Steals Crypto Wallets & SSH Keys" — https://www.cryptotimes.io/2026/05/25/trapdoor-malware-hits-npm-pypi-crates-io-steals-crypto-wallets-ssh-keys/
Internal Safeguard resources: