Someone Is Hiding Instructions in Your CLAUDE.md - Here Is a Free Tool That Finds Them
- Patrick Duggan
- 4 hours ago
- 5 min read
If you use Claude Code, Cursor, Copilot, Cline or Windsurf, there is a file in your repository that your AI agent reads before it does anything else. It is called CLAUDE.md, or .cursorrules, or copilot-instructions.md. It is the standing brief. Every session, every invocation, the model reads it and takes it as direction.
It is also, in most repositories, a file nobody reviews carefully. It is prose, not code. It does not run. It has no tests. When it shows up in a pull request, it gets a glance and an approval.
The TrapDoor supply-chain campaign, documented by Socket, noticed that.
The attack
Attackers submitted pull requests to prominent open-source AI projects — LangChain, MetaGPT, OpenHands among them — containing modified .cursorrules and CLAUDE.md files.
The modifications were written in zero-width Unicode: codepoints that occupy no visual space at all. They do not render in an editor. They do not render in a GitHub diff. They survive copy and paste. And they are delivered to the language model as ordinary instruction text, because as far as the model is concerned that is exactly what they are.
Same file. Same bytes. Two entirely different documents depending on who is reading.
The engineer reviewing that pull request is not being careless. There is nothing on the screen to be careless about.
Why this one is worth taking seriously
Most supply-chain attacks come through dependencies. You pull a package, the package has a postinstall script, the script does something it should not. That is bad, and there is an established defensive stack for it: lockfiles, provenance, deny-lists, scanners.
This is different in a way that matters. The payload is not code. It is instruction.
It does not execute. It persuades. It arrives inside the one file in your repository whose entire purpose is telling the AI what to do, and it arrives with all the authority that file carries. Your agent is not exploited in any traditional sense. It is briefed.
And it persists. A malicious dependency gets removed when you bump the version. A poisoned instruction file sits in your repository being read, correctly and faithfully, on every single invocation until somebody notices — and the whole design of the attack is that nobody notices.
We checked ourselves first
We publish a CLAUDE.md. So do four other repositories we maintain. Before writing a word of this, we scanned all of them, plus every rule file and skill definition in the platform.
Eleven agent instruction files. Zero invisible characters. We are clean.
That check took under a second, which tells you something about the economics here. The attack is genuinely nasty; the detection is genuinely trivial. The characters either are present or they are not. There is no heuristic, no model, no confidence score, no false-negative rate to argue about.
So we built the check and we are giving it away.
The tool
[github.com/pduggusa/dugganusa-agent-guard](https://github.com/pduggusa/dugganusa-agent-guard) — around a hundred lines, no dependencies, MIT. Run it without installing anything: npx github:pduggusa/dugganusa-agent-guard
It runs entirely on your machine. There is no hosted version and there will not be one — the obvious product here is an API where you send us your CLAUDE.md and we tell you whether it is poisoned, and that would mean ingesting other people's agent instructions, internal conventions and architecture notes onto our servers. That is not a trade we get to make on your behalf. The detection needs no server anyway: the characters are present or they are not.
It scans the files AI agents actually read as instructions — CLAUDE.md, AGENTS.md, .cursorrules, .clinerules, .windsurfrules, copilot-instructions.md, GEMINI.md and a few more — for nineteen invisible codepoints. Zero-width spaces and joiners. Bidirectional embeddings and overrides, which is the Trojan Source class. Invisible mathematical operators. Soft hyphens. Mid-file byte-order marks.
For each finding it reports severity, the codepoint, the exact line and column, and the containing line with the invisible characters made visible so you can see what was hidden and where.
It exits non-zero when it finds something, so it drops straight into a pre-commit hook or a CI step. There is a JSON mode for pipelines, an option to widen the scan to ordinary source files, and a strip mode that removes the characters while preserving the original alongside it, because destroying evidence during incident response is its own mistake.
The design decision that actually matters
The hard part of this tool is not detection. It is not crying wolf.
Zero-width joiners are used legitimately, constantly, inside emoji. The family emoji is three people glued together with the same codepoint an attacker would use to hide text. A byte-order mark at the start of a file is completely ordinary. A naive scanner flags all of it, floods you with noise, and gets switched off within a week.
A switched-off checker is worse than no checker, because it leaves behind the belief that you are covered.
So: a zero-width joiner sitting between two emoji is ignored. A leading byte-order mark is ignored. A byte-order mark in the middle of a file is flagged, because there is no innocent reason for one to be there. Those three rules are the difference between a tool people run and a tool people mute.
We wrote tests for the false positives before we wrote tests for the attack, which is the correct order for anything that will live in someone else's build pipeline.
What to do
Run it against your repository. It takes a second and it is free.
If it finds something, do not just strip it — look at what the hidden text said and check your history for when it arrived, because the answer tells you whether you have a poisoned file or a poisoned contributor.
More generally: start reviewing your agent instruction files like code. They are executable in every sense that matters. They carry more authority over your AI tooling than most of your actual source does, and right now they are getting waved through code review because they look like documentation.
That is the gap this campaign found. It is a good one, and it will not be the last time somebody uses it.
Credit and limits
The campaign and its use of poisoned instruction files were discovered and documented by Socket, who did the primary research. We built a detector for one technique in it. That is a much smaller contribution than finding the thing in the first place, and we would rather say so than blur the line.
What we cannot tell you: whether your specific repository has been targeted, or whether this technique is more widespread than the cases Socket documented. We have not surveyed the ecosystem and we are not going to guess at a number. We can tell you that the check is free, deterministic, and takes a second, which makes the survey somewhat beside the point.
We cap our confidence at 95 percent as a matter of policy. On this one the detection itself is about as close to certain as security tooling gets — the characters are present or they are not. It is everything around it, including whether we have thought of every file an agent might read, where the remaining five percent lives.
How do AI models see YOUR brand?
AIPM has audited 250+ domains. 15 seconds. Free while still in beta.




Comments