If you use Claude Code or Cursor, you need to read this. Attackers just shipped a new prompt-injection method that hides instructions inside CLAUDE.md and .cursorrulesfiles using invisible Unicode characters. Your AI reads them. You don't.
Socket.dev published the full breakdown on May 24, 2026: socket.dev/blog/trapdoor-crypto-stealer-npm-pypi-crates. The campaign is called TrapDoor.
What happened
- 34 malicious packages, 384+ versions across npm, PyPI, and Crates.io.
- The same GitHub account (
ddjidd564) also opened pull requests against LangChain, LlamaIndex, MetaGPT, Langflow, OpenHands, and browser-use, all titled things like "docs: add .cursorrules with dev standards and build verification". - Decoy package names blend in on purpose:
prompt-engineering-toolkit,solidity-deploy-guard,defi-threat-scanner,eth-wallet-sentinel,sui-sdk-build-utils,token-usage-tracker. - First seen on PyPI 22 May 2026 (
eth-security-auditor@0.1.0). Socket caught new releases in an average of 5 min 56 sec.
How the trick works
The attacker drops a modified .cursorrules or CLAUDE.md into the project. To you in your editor it looks normal, maybe a few lines about "dev standards". Inside it are zero-width Unicode characters (U+200B, U+200C, U+200D, U+2060, U+FEFF and similar). Those characters render as nothing. Zero pixels. But the AI tokenises them and reads them as instructions.
The hidden prompt tells the agent to run an "automated project security scan". The scan actually walks your machine and exfiltrates:
- SSH keys
- Solana, Sui, and Aptos wallet keystores
- Browser profiles and login databases
- Crypto wallet browser-extension data
- AWS credentials, GitHub tokens, env vars, API keys
The npm payload (trap-core.js, 1,149 lines) installs persistence through systemd services, cron jobs, Git hooks, and shell hooks. One npm install on a poisoned package is enough.
How to check your own files
The fix is the same idea your editor hides from you: stop looking at rendered text, look at the raw bytes. A hex view shows every character as a number, so zero-width chars become visible.
macOS and Linux
Dump the file as hex and scroll through:
xxd ~/.claude/CLAUDE.md | lessAnything beyond plain ASCII shows up in the hex column. Hidden chars like e2 80 8b (U+200B, zero-width space), e2 80 8c, e2 80 8d, e2 81 a0, or ef bb bf appearing mid-file are red flags.
Or scan straight for the dangerous ranges with Perl (works on macOS by default):
perl -ne 'print "line $.: $_" if /[\x{200B}-\x{200F}\x{2028}-\x{202F}\x{2060}-\x{206F}\x{FEFF}]/' ~/.claude/CLAUDE.md .cursorrules 2>/dev/nullNo output means clean. Any output is a file you should not load into an agent until you understand the line.
Windows (PowerShell)
PowerShell 5.1+ ships Format-Hex built in:
Format-Hex .\CLAUDE.md | moreSame idea, same red flags (E2 80 8B, E2 80 8C, EF BB BF mid-file, etc).
For a one-shot scan that flags any non-ASCII character:
Get-Content .\CLAUDE.md | Select-String '[^\x00-\x7F]'What to do right now
- Run the command above on every
CLAUDE.md,.cursorrules, andAGENTS.mdin your projects, including the global ones at~/.claude/CLAUDE.mdand~/.cursor/. - Audit recent
npm install,pip install, andcargo addactivity for the package names above. Socket has the full IOC list. - If you ever cloned a repo and accepted its
.cursorruleswholesale, re-open it inxxdbefore letting an agent touch it again. - Treat any PR that adds or edits an AI config file as security-sensitive. The TrapDoor PRs looked like documentation cleanup.
The takeaway: any file your agent reads is executable input. Including the markdown ones.