Socket
disclosed a coordinated, multi-ecosystem campaign it calls
TrapDoor: at least 34 malicious
packages and 384+ related versions and artifacts
published across npm, PyPI, and Crates.io,
built to steal cryptocurrency wallets and developer credentials.
The packages are not hijacks of popular libraries; they are
net-new lures with names crafted to attract crypto, DeFi,
Solana, Sui/Move, AI, and security developers
(wallet-security-checker,
defi-threat-scanner,
eth-wallet-sentinel,
move-compiler-tools, and similar). On install,
import, or build, they run a shared payload that harvests
SSH keys; Sui, Solana, and Aptos wallet data; AWS
credentials; GitHub tokens; browser profile and login data;
crypto-wallet extension data; environment variables; API keys;
and local dev-config files, then exfiltrates to
attacker-controlled GitHub infrastructure. This is a
HIGH-severity, actively-maintained campaign
(the operator pushed new releases repeatedly, and some packages
were still live at the time of Socket's writeup). The single
most useful action: grep your npm, pip, and cargo
lockfiles for the named packages, and if any host installed,
built, or imported one, treat it as credential- and
wallet-compromised.
Framing note: at publication this is essentially single-source (Socket), and Socket's report is thin on classic network IOCs: it names the attacker's GitHub account and payload markers but does not publish C2 IP addresses, file hashes, exfiltration Gist URLs, or wallet addresses, and it gives no install/download counts, so the true blast radius is unknown. The actionable surface here is the package names plus the install/import/build execution behavior, not a hash or egress-block list. A separate, unrelated "Trapdoor" Android ad-fraud story was reported in May 2026; this bulletin is not about that.
Three properties make this worth stopping for, even though
the named packages are obscure. First, execution is
automatic and pre-runtime. The npm packages run via
postinstall hooks (fires on
npm install), the PyPI packages auto-execute on
import, and the Crates.io packages run a
malicious build.rs during
cargo build. For npm and Crates.io you do not
have to call the library: an npm install or a
cargo build alone runs the payload, even if the
package is later removed or only pulled in transitively. The
PyPI packages run on import, so a
pip install that is never imported does not fire,
but an import by your code, a dependency, a test run, or
tooling does.
Second, the loot is high-value and irreversible.
The payload specifically targets Sui, Solana, Aptos, and
web3 wallet material and mnemonic phrases. A stolen seed
phrase is a permanent compromise of every asset that wallet
controls, and rotating it is not "change a password," it is
"move funds to a wallet generated on a clean device."
Third, it has a self-spreading angle.
Stolen GitHub tokens and credentials enable further pushes,
and Socket documents a secondary vector that injects hidden
instructions into AI/agent config files
(.cursorrules, CLAUDE.md) via pull
requests. Calibrated read: the blast radius is bounded to
whoever installed one of the lures, but for those who did,
treat it as a full credential incident.
ddjidd564.github.io host and the
trap-core.js / cargo-build-helper-2026
/ P-2024-001 strings are usable hunt markers for
proxy logs and on-disk search, but they are not a substitute
for the package-name inventory. Because the operator was
repeatedly republishing, expect re-uploads under new names;
the names above are a point-in-time list, not a closed set.
Priorities, by environment
Unlike a hijack of a popular dependency, TrapDoor only reaches you if a developer (or a transitive dependency, or a CI step) pulled one of these specific lure packages. The triage question is therefore "did anything in my environment install, import, or build one of the named packages," and "what could that host reach." The bands below reflect Socket's described targeting and the install/import/build execution behavior.
| Priority | Environment | Why |
|---|---|---|
| Highest | Crypto / DeFi / Solana / Sui / Move developer workstations with hot wallets, seed phrases, or signing keys present | This is the bullseye. The payload pulls Sui, Solana, Aptos, and web3 extension wallet data and mnemonic material directly. If a host that ever held a wallet seed or private key installed any named package, assume the seed is compromised and move funds off it immediately (see step 02). |
| Higher | AI / ML and security-tooling developers who installed packages with security- or AI-flavored names | The lures are named to attract exactly this audience: defi-threat-scanner, crypto-credential-scanner, web3-secrets-detector, prompt-engineering-toolkit, llm-context-compressor, model-switch-router. Someone evaluating "a tool that audits my secrets" is the intended victim. Treat any such install as credential exposure. |
| Higher | Any host where npm install, import, or cargo build ran against a named package |
Execution does not require deliberately "using" the library: an npm postinstall hook (on install), a Crates.io build.rs (on build), or a Python import is sufficient. An npm or cargo package that landed transitively or was tried and discarded still ran; a PyPI package ran if anything imported it. Scope by what executed, not by what stayed. |
| Medium | CI/CD runners and build agents that resolved any candidate package | CI runners commonly hold cloud credentials, registry tokens, and signing material, and they run installs and builds unattended. Stolen npm/GitHub tokens feed the self-propagation and re-publishing angle. Audit lockfiles used in CI and rotate any tokens those runners hold. |
| Medium | Repos that merged PRs touching .cursorrules or CLAUDE.md from unfamiliar contributors |
Socket documents a secondary vector: pull requests that inject hidden-Unicode instructions into AI/agent config files. Review recent edits to those files, especially from outside contributors (see step 04). |
| Lower | Environments with no lockfile match across npm / pip / cargo and no relevant config-file PRs | If a grep across your package-lock.json / yarn.lock / pnpm-lock.yaml, requirements / poetry.lock / uv.lock, and Cargo.lock returns nothing for the named packages, you are very likely unaffected. Keep the names handy for re-uploads under new identifiers. |
Categorization source: Bulletin's framing, derived from Socket's described targeting (crypto / DeFi / Solana / Sui-Move / AI / security developers) and the per-ecosystem execution behavior. Socket did not publish a victim-priority schema or install counts.
Am I affected?
npm postinstall fires during
npm install, and the Crates.io payload runs
during cargo build via build.rs, so
for those two an install or build alone executed the payload,
even if the package was later removed or only pulled in
transitively. The PyPI payload runs on import, so
a pip install that was never imported did not
fire, but an import by your own code, a dependency, a test
run, or tooling counts. Inventory by what was
installed, built, or imported, not by what you
remember using, and treat any lockfile hit as possible
compromise until you can rule out execution.
Inventory your lockfiles (bash / grep)
Run each of these from the root of a tree containing your projects. Each is a single line. npm:
grep -rEn 'async-pipeline-builder|build-scripts-utils|chain-key-validator|crypto-credential-scanner|defi-env-auditor|defi-threat-scanner|deployment-key-auditor|dev-env-bootstrapper|eth-wallet-sentinel|llm-context-compressor|mnemonic-safety-check|model-switch-router|node-setup-helpers|project-init-tools|prompt-engineering-toolkit|solidity-deploy-guard|token-usage-tracker|wallet-backup-verifier|wallet-security-checker|web3-secrets-detector|workspace-config-loader' --include='package-lock.json' --include='yarn.lock' --include='pnpm-lock.yaml' --include='package.json' .
PyPI:
grep -rEn 'cryptowallet-safety|data-pipeline-check|defi-risk-scanner|env-loader-cli|eth-security-auditor|git-config-sync|solidity-build-guard' --include='requirements*.txt' --include='poetry.lock' --include='Pipfile.lock' --include='pdm.lock' --include='uv.lock' --include='pyproject.toml' .
Crates.io:
grep -rEn 'move-analyzer-build|move-compiler-tools|move-project-builder|sui-framework-helpers|sui-move-build-helper|sui-sdk-build-utils' --include='Cargo.lock' --include='Cargo.toml' .
Confirm any hit with the native resolver:
npm ls <name>,
pip show <name>, or by
inspecting the [[package]] stanza in
Cargo.lock.
Hunt for execution artifacts and the staging host
Search installed trees and logs for the campaign markers. The payload filename and staging domain are the most useful on-disk and proxy-log signals Socket provided. bash:
grep -rEl 'trap-core\.js|ddjidd564\.github\.io|cargo-build-helper-2026|P-2024-001' node_modules ~/.cargo ~/.npm "$HOME/.cache" . 2>/dev/null
PowerShell (Windows):
Get-ChildItem -Path . -Recurse -File -ErrorAction SilentlyContinue | Select-String -Pattern 'trap-core\.js','ddjidd564\.github\.io','cargo-build-helper-2026','P-2024-001' -List | Select-Object Path,LineNumber
In proxy, DNS, and EDR network telemetry, look for any outbound
connection to ddjidd564.github.io on or after
May 22, 2026 (the earliest observed artifact),
and for a Python or Rust build process spawning
node -e (the PyPI path stages JavaScript from the
GitHub Pages host and runs it through Node). Because exfil
reportedly goes to GitHub Gists under the victim's own account,
also review your GitHub account for unexpected Gists created in
that window.
Check AI/agent config files for the PR-injection vector
Flag .cursorrules and CLAUDE.md files
that contain hidden-Unicode control characters (zero-width,
bidirectional overrides). This single-line ripgrep check lists
any such file (it needs ripgrep installed):
rg --hidden --no-ignore -l '[\x{200b}-\x{200f}\x{202a}-\x{202e}\x{2060}-\x{206f}\x{feff}]' -g '.cursorrules' -g 'CLAUDE.md' -g '!node_modules/**' -g '!.git/**' .
Then read any flagged file (and any recent PR that touched one) with a normal editor and review the literal instructions, not just the rendered text.
Response, if any host installed, imported, or built a named package
- Inventory across all three ecosystems first. Run the three lockfile greps above everywhere developers and CI operate, not just the one ecosystem you think you use. TrapDoor spans npm, PyPI, and Crates.io simultaneously, and a polyglot monorepo or a developer who dabbles in Move/Rust can be hit on an axis you were not watching.
- Treat any matched host as wallet- and credential-compromised, and move crypto funds now. For wallets, this is the irreversible part: assume every seed phrase, mnemonic, and private key that was present on the host (Sui, Solana, Aptos, Ethereum/web3 browser extensions, hardware-wallet companion files) is in attacker hands. Generate a fresh wallet on a known-clean device and move assets to it. Re-importing the same seed elsewhere does not help, the seed is the secret that leaked.
- Rotate GitHub and registry tokens, and review for unauthorized publishes. Stolen GitHub credentials and npm tokens are what give this campaign a self-spreading and re-publishing capability. Revoke and reissue GitHub PATs, npm tokens, and any CI registry credentials the host or runner held. Check your npm / PyPI / crates.io publish history and your GitHub Gists and repos for activity you did not perform.
-
Remove the packages and the secondary config injections.
Delete the offending dependencies, repin to a known-good
version or remove them entirely, and rebuild from a clean
state: delete
node_modulesand reinstall from a cleaned lockfile for npm; recreate the virtualenv for PyPI; for Rust, remove the crate and itsCargo.lockentry, runcargo cleanto drop compiledbuild.rsoutput, and clear the cached source under$CARGO_HOME/registry(a maliciousbuild.rscan also write outsidetarget/, so package cleanup is hygiene, not the fix, credential and wallet rotation in step 02 is). Separately, revert any hidden-Unicode injections found in.cursorrules/CLAUDE.mdand audit the PRs that introduced them. -
Block and hunt the staging host. Where you
can, block
ddjidd564.github.ioat egress and search historical proxy/DNS/EDR logs for connections to it since May 22, 2026. Note this is a GitHub Pages subdomain, so a blunt block ongithub.iowill catch unrelated legitimate traffic; scope to the full host. There is no C2 IP or hash list from Socket to add beyond this. -
Report still-live packages and watch for re-uploads.
Socket says it reported the packages to the registries and
that some were still live at the time of writing. If your
grep turns up a package that is still installable, report it
to the relevant registry's security contact. Keep the name
list and the publisher handles
(
asdxzxc,asdmini67,dae5411,ddjidd564) on hand, the operator was actively pushing new releases, so expect the same payload under new package names. - Reimage where a host held high-value wallet or production material. For a workstation that held a hardware-wallet seed backup, production signing keys, or broad cloud access, a credential rotation alone leaves residual-implant risk. Wipe and rebuild from clean media, and only restore data, not executables or cached package artifacts, from before the incident window.
The broader pattern
TrapDoor is the newest entry as of this writing in the supply-chain run this Bulletin has tracked since April 2026 (the PyTorch Lightning, mistralai, xinference, Bitwarden CLI, and Checkmarx compromises). Three things make it worth distinguishing from those.
First, it is a single campaign operating across three registries at once. The April compromises were each anchored to one ecosystem; TrapDoor publishes coordinated lures on npm, PyPI, and Crates.io together. Lockfile hygiene that only covers your "main" language leaves the other two axes open, and the Move/Rust angle in particular is one most JS/Python shops do not scan.
Second, it targets intent, not popularity.
The Lightning/mistralai pattern hijacked packages people already
depended on. TrapDoor instead bets that crypto, DeFi, and
AI-curious developers will go looking for a
wallet-security-checker or a
defi-threat-scanner and install it. The defense is
not just pinning known-good dependencies, it is treating
"install a tool that promises to audit my secrets" as the
high-risk action it is.
Third, the AI-agent config injection is newer
tradecraft this audience should note. Slipping
hidden-Unicode instructions into .cursorrules and
CLAUDE.md via pull requests aims squarely at
developers who let coding agents read repo-local instruction
files. If your team runs agents against checked-out repos,
those instruction files are now part of your trust boundary and
deserve review like any other executable input.
At publication, Socket is effectively the sole source for the TrapDoor name and package list. Socket did not publish C2 IP addresses, payload file hashes, exfiltration Gist URLs, or wallet addresses, so this bulletin cannot offer a hash-match or egress-IP block list, only package names, the GitHub Pages staging host, and a few marker strings. Install and download counts were not given, so the real number of affected hosts is unknown. Socket's own post is inconsistent on the package count (34 enumerated vs. 36 stated); 34 is used here. Attribution is open, only the publisher handles are known. The package list is point-in-time: the operator was actively republishing, and some packages were still live at the time of writing, so new names under the same payload should be expected. This bulletin will be updated if Socket or independent researchers publish concrete network IOCs or confirmed victim impact.
Grep every npm, pip, and cargo lockfile in your environment
for the 34 named TrapDoor packages; if any host installed,
imported, or built one, treat it as wallet- and
credential-compromised: move crypto funds to a fresh wallet
generated on a clean device (the seed leaked, so re-importing
it does not help), rotate SSH keys, AWS creds, GitHub and
registry tokens, API keys, and .env secrets the
host could reach, remove the packages and rebuild clean
(cargo clean for Rust), block
ddjidd564.github.io at egress, and review your
repos' .cursorrules / CLAUDE.md for
injected instructions. Package names, not hashes, are the
detection signal, and expect re-uploads under new names.