Back to all posts
Security

Instruction File Injection: How AGENTS.md and CLAUDE.md Hijack Coding Agents

AGENTS.md and CLAUDE.md load with near system-prompt authority. How instruction file injection works, the named 2026 incidents, and how to defend your repo.

On this page
  1. What is instruction file injection?
  2. The files that carry system-prompt authority
  3. Why the trust dialog is not a security boundary
  4. Anatomy of the attack: one minute fifty-one seconds
  5. Six ways an instruction file gets poisoned
  6. 1. The repository you were asked to clone
  7. 2. A pull request from a fork
  8. 3. A marketplace skill or plugin
  9. 4. An MCP config swap
  10. 5. A vendored or transitive instruction file
  11. 6. Your own repository, from the inside
  12. What the built-in controls cover, and what they do not
  13. Eight controls that actually reduce the risk
  14. Where the controls stop: instruction files are code you never review
  15. Frequently asked questions
  16. Can a Markdown file really execute code?
  17. Is it safe to commit an AGENTS.md or CLAUDE.md to my repository?
  18. Does the trust dialog protect me?
  19. Which files should I put under mandatory review?
  20. Can I detect instruction file injection with grep?
  21. Does this affect Copilot and Cursor too, or just Claude Code?
  22. How is this different from slopsquatting or a malicious package?
  23. What should I do first if I think an agent followed a poisoned instruction file?

Instruction file injection: a repository whose AGENTS.md, CLAUDE.md and .cursor/rules feed straight into a coding agent's trusted context, with a policy guard reading the same files first.

On a June morning in 2026, a developer cloned a take-home coding test and opened it in their editor. The repository contained no malware. No post-install script, no obfuscated binary, no suspicious dependency. What it contained was a .cursor/rules file, a CLAUDE.md, a README.md with hidden HTML comments, and a .cursor/mcp.json. One minute and fifty-one seconds after the agent read those files, it had dumped the developer's AWS credentials, identified the account, read the Kubernetes config, enumerated the Terraform state, grepped the codebase for secrets, and shipped everything out through an MCP tool call. Nobody typed a single one of those commands. This is instruction file injection, and it is the attack that the pull request cannot see.

What is instruction file injection?

Instruction file injection is an indirect prompt injection attack in which the payload lives in a repository file that an AI coding agent loads as trusted project guidance rather than as untrusted input. The attacker never talks to the model. They commit a file, and the agent reads it on your behalf, on your machine, with your credentials.

It is worth being precise about why this is a different class of problem from the prompt injection everyone already knows about. Classic indirect injection hides instructions in content the model happens to fetch: a web page, a Jira ticket, the body of an issue. The model is supposed to treat that as data, and the failure is that it sometimes treats it as instruction. Instruction file injection inverts the framing. These files are designed to be instructions. Loading them as policy is not a bug, it is the documented feature. CLAUDE.md exists so that a repository can tell the agent how the project works. AGENTS.md exists so that the agent picks up conventions without being told. The whole value proposition is that the agent obeys the file.

So the vulnerability is not "the model confused data for instructions." The vulnerability is that the file is authoritative and the authorship is not verified. The Cloud Security Alliance put it plainly in its March 2026 research note on README injection: these files are loaded at session startup and treated with a level of trust that approximates system-prompt authority, so an adversary who can modify them effectively controls the agent's behavioural policy for every subsequent interaction in that repository.

A dependency has to be installed to hurt you. An instruction file only has to be read.

- The shift, in one line

That asymmetry is what makes this cheap to exploit. Supply chain attacks against packages need a registry, a version bump, an install step and usually a lifecycle script. Instruction file injection needs a text file and someone who opens the folder. There is nothing to detect at install time because nothing is installed. There is nothing to catch in the dependency graph because no dependency changed. And there is frequently nothing in the diff either, because on a fresh clone there is no diff at all.

The files that carry system-prompt authority

The first defensive move is knowing your own instruction surface. Most teams underestimate it by a factor of five, because they think of it as "the CLAUDE.md we wrote" and forget the settings file, the skills directory, the MCP config and the per-subdirectory overrides.

AgentFiles loaded as instruction or policyLoad behaviour
Claude CodeCLAUDE.md, .claude/settings.json (hooks), .claude/skills/*/SKILL.md, .claude/agents/*.md, installed plugin configProject-level configuration under .claude/ is loaded once the directory is trusted
OpenAI CodexAGENTS.mdThe CLI walks the directory tree and loads every AGENTS.md it finds
Gemini CLI and its Antigravity successorGEMINI.mdDiscovered and loaded as trusted project memory
Cursor.cursor/rules, legacy .cursorrules, .cursor/mcp.jsonRules apply to matching files; the MCP config defines which tools exist
Cline.clinerulesLoaded as project rules for the session
GitHub Copilot.github/copilot-instructions.mdPrepended to requests in that repository
Windsurf.windsurfrules and the .windsurf/rules directoryLoaded as workspace rules
Every agent, indirectlyREADME.md, CONTRIBUTING.md, issue titles, pull request descriptions, code comments, dependency descriptions, MCP tool descriptionsRead into context during normal work, not marked as untrusted

Two rows deserve a second look.

The .claude/settings.json row is not a metaphor. Hooks are shell commands that the agent runs around its own tool calls, and they are defined in a file that lives in the repository. That is why CVE-2025-59536 exists: in Claude Code before version 1.0.111, code execution was possible before the user accepted the startup trust dialog, via untrusted project hooks defined in .claude/settings.json. It carries a CVSS v4.0 base score of 8.7. The fix shipped in 1.0.111, and the lesson outlived the patch: a JSON file in a repository was a remote code execution primitive because the agent was designed to execute what it declared.

The last row is the one that keeps growing. Every surface an agent reads during ordinary work is a candidate channel, and researchers keep finding new ones. The Cloud Security Alliance documented prompt injection reaching claude-code-action through GitHub Actions, and the GitInject research published in June 2026 catalogued real-world prompt injection in AI-powered CI/CD pipelines. If the agent reads it, an attacker can write it.

Why the trust dialog is not a security boundary

Every serious agent now shows a consent prompt the first time you open an unfamiliar folder. It is a genuinely useful control, and it is also the single most misunderstood one in the category, because of what it is actually asking.

It asks whether you trust the directory. It does not, and cannot, tell you anything about the content of the instruction files inside it. Consent is granted at the granularity of a folder, then applied to an arbitrary amount of attacker-controlled policy text. You are asked one question, once, and you answer it before you have read a single rule file.

The clearest demonstration of this gap came from Hookify, a plugin distributed through Anthropic's own official Claude Code marketplace. Hookify is a rule engine: it reads rule files from the project directory, expressed as Markdown with YAML front matter, and feeds their content into the hook subsystem's trusted system-message channel. Security researchers at Pluto Security reported that an attacker who plants such a file in a repository therefore gets a steering channel into the model for any user who has Hookify installed and opens the repo. Against Claude Opus 4.6, five behavioural payloads framed as innocuous project conventions were enough to make the model leak environment variables and local-only secrets.

Anthropic's response is the part worth internalising. The report was closed as Informative, working as designed: the directory trust dialog is the security boundary, and once it is accepted, project-level configuration under .claude/, including CLAUDE.md, project hooks and plugin configuration such as Hookify rule files, is intentionally loaded.

That answer is defensible on its own terms. It is also a precise statement of the residual risk you now own.

This is also why "just read the files before you accept" fails in practice. The instruction surface is spread across a settings file, a rules directory, a per-subdirectory Markdown convention, a skills folder and an MCP config. Payloads sit in HTML comments that render as nothing. And the moment you clone a monorepo, the tree can hold a dozen nested instruction files, any one of which can override the ones above it.

Anatomy of the attack: one minute fifty-one seconds

The take-home coding test documented by Mitiga in June 2026 is the cleanest public example, because the timestamps show exactly how little time a human has to intervene.

Clone a normal-looking repositoryAgent loads .cursor/rules, CLAUDE.md, README comments, .cursor/mcp.jsonAgent harvests cloud and cluster credentialsAgent exfiltrates through an MCP tool call
The poisoned take-home test: from opening the folder to exfiltration, with no human command in between.
ElapsedWhat the agent did
00:00Ingested the malicious instructions from the configuration files
00:29cat ~/.aws/credentials
00:42aws sts get-caller-identity, to identify the account
00:58cat ~/.kube/config
01:09Enumerated infrastructure through Terraform commands
01:30Grepped the codebase for secrets
01:51Exfiltrated the collected data through an MCP tool call

Read that table as an incident response exercise and the problem becomes obvious. The window between the first hostile action and full exfiltration is under two minutes. There is no pull request. There is no build. There is no artifact to scan. Every control that lives downstream of the commit is looking in the wrong place, because the attack completed before any code was written, let alone reviewed.

Note also what the attacker did not need. No zero-day. No malicious package. No compromised maintainer account. They needed a plausible reason for you to clone a repository, which for anyone hiring or job hunting is the easiest social engineering in the industry.

Six ways an instruction file gets poisoned

The take-home test is one delivery route. It is not the interesting part of the threat model, because it requires you to clone something new. These are the routes that reach repositories you already trust.

1. The repository you were asked to clone

Interview exercises, bug reproductions, "can you take a look at this" links, conference workshop repos, template starters. Anything that comes with a legitimate reason to run an agent inside it. The Mitiga case is this route, and it works because the request is genuine and the payload is invisible.

2. A pull request from a fork

This is the route that scales, because it reaches your repository without any social engineering. If an agent workflow runs with write permissions on fork-originated events, a contributor's branch can add or modify AGENTS.md, .clinerules or a rules directory, and the agent will read the attacker's version. The Clinejection chain, publicly disclosed on 9 February 2026 and documented by Snyk, is the industrial version of this: prompt injection through issue titles turned Cline's automated triage workflow into a supply chain attack vector, and an unknown actor used it to publish an unauthorised version of the Cline CLI to npm during an eight-hour window.

3. A marketplace skill or plugin

Agent skills are instruction files with a distribution channel, which is the worst possible combination. Snyk's ToxicSkills study of the ClawHub registry found prompt injection in 36% of the skills analysed and catalogued 1,467 malicious payloads. Because skills persist across sessions once enabled, a single install decision keeps shaping agent behaviour indefinitely, in every repository you open afterwards. OWASP now maintains an Agentic Skills Top 10, which tells you how quickly this became its own category.

4. An MCP config swap

.cursor/mcp.json and its equivalents declare which tools exist and what their descriptions say. Change the config and you change the agent's available actions; change a tool description and you change the model's understanding of what that action means. This is the same mechanism as MCP tool poisoning, which we covered in MCP security and tool poisoning, arriving through a repository file instead of a server.

5. A vendored or transitive instruction file

Instruction files travel. A vendored subtree, a git submodule, a scaffolded template, a node_modules directory an agent decides to read: each can carry its own AGENTS.md. Because most agents walk the tree and load what they find, a nested file placed deep in a dependency can quietly override the conventions you wrote at the root.

6. Your own repository, from the inside

The least dramatic and most likely. Instruction files are usually exempt from the review culture that surrounds source code. They are not in CODEOWNERS, they do not trip a required reviewer, and they read as documentation. Anyone with commit access, including a compromised developer account or a well-meaning contributor who copied a rule from a blog post, can change the operating policy of every agent on the team without a single security eye on the diff.

What the built-in controls cover, and what they do not

Agent vendors have shipped real controls, and it would be dishonest to imply otherwise. Sandboxes limit where writes land. Approval ladders create checkpoints. Network defaults are closed in several cloud modes. Terminal allowlists and deny lists exist. Antigravity ships a browser URL allowlist specifically to cut the injection path through fetched pages. All of that reduces risk.

The gap is narrower and more specific than "agents are unsafe."

Question
Built-in agent controls
What is still missing
Can an unknown folder run code?
Trust dialog gates the session
Once accepted, every instruction file in the tree is authoritative
Is the instruction content checked?
No content inspection at any point
Nobody verifies who wrote the rule the agent is about to obey
Can the agent reach my credentials?
Sandbox limits writes, not reads
Reading ~/.aws and ~/.kube is normal agent behaviour
Does review catch it?
Pull request review covers source
Instruction files are rarely owned, rarely reviewed
Does it survive the session?
Approvals reset per session
Installed skills and plugins persist across every repo

Put simply: the controls are about capability, and instruction file injection is about authority. Sandboxing answers "what can this process touch." It has nothing to say about "whose instructions is the model following." Those are orthogonal, which is why a perfectly sandboxed agent will still happily read a credentials file and hand it to a tool, if the policy it loaded told it to.

This is the same structural point OWASP keeps making about agentic systems in production, where prompt injection remains the dominant driver of security failures rather than a solved category.

Eight controls that actually reduce the risk

Nothing here requires a new vendor. Most of it is policy and plumbing, and it is worth doing before you buy anything.

Treat instruction files as executable code

Add AGENTS.md, CLAUDE.md, .clinerules, GEMINI.md, .cursor/**, .claude/**, .windsurf/** and .github/copilot-instructions.md to CODEOWNERS with a security reviewer. The Cloud Security Alliance's recommendation is exactly this: subject them to the same review, approval and least-privilege controls you apply to any executable admitted to a repository.

Fail the build when the instruction surface changes

A CI check that lists modified paths and fails on any instruction file change without a security approval costs about twenty lines of YAML. It converts an invisible policy edit into a visible decision.

Clone unknown repositories into a throwaway container

Move the trust boundary from the session to the machine. A dev container with no cloud credentials, no kubeconfig and no SSH agent turns the Mitiga timeline into six failed commands.

Starve the agent of credentials it does not need

An agent writing CSS does not need production keys mounted in its environment. Scope the .env you hand each session, keep long-lived cloud credentials out of the agent's HOME, and prefer short-lived scoped tokens.

Deny the exfiltration verbs, not only the destructive ones

Most deny lists stop at rm, sudo and git push. Exfiltration needs a way out: curl, wget, nc, base64, and any command that prints your environment. Add those, and keep the network closed by default.

No auto-approve on code you did not write

Auto-approve for shell execution and browser access is a reasonable convenience in a repository you own. It is the enabling condition for this entire attack class in a repository you do not. Keep the toggle per project, not global.

Vet skills and plugins like packages

Pin versions, disable auto-update, read the SKILL.md before enabling, and keep the enabled set small. Remember that a skill enabled for one project keeps steering the agent in every project afterwards.

Never run an agent workflow with write access on fork events

pull_request_target with write permissions plus an agent that reads repository files is the Clinejection shape. Split the privileged step from the untrusted checkout, or do not run the agent on forks at all.

Two things this list deliberately does not include. It does not tell you to stop using instruction files, because they are the mechanism that makes agents useful on a real codebase and removing them just makes the agent guess. And it does not tell you to read every rule file before accepting a trust dialog, because that advice does not survive contact with a monorepo.

Where the controls stop: instruction files are code you never review

Work through the eight controls above and you will have closed the delivery routes you can see. What remains is the structural problem, and it is the reason we built CybeDefend the way we did.

An instruction file is executable policy that no part of your toolchain reads as code. Your SAST scanner parses source; it does not parse Markdown that reprograms an agent. Your dependency scanner reads manifests; a rules file has no manifest. Your secret scanner looks for keys; this payload contains none. And your pull request review, the place where application security has lived for fifteen years, only sees the change after an agent has already spent a session obeying it. The Mitiga timeline is the proof: the whole incident finished 1 minute 51 seconds after a folder was opened, which is roughly a thousand times faster than the review cycle designed to catch it.

That cadence mismatch is the thesis of this entire site. Security review as a gate assumed a human bottleneck between intent and code. Agents removed the bottleneck. We wrote about the general form of this in AI coding agent security, and instruction file injection is its sharpest instance, because here the attacker's payload and the agent's operating manual are literally the same file.

So the control has to sit where the decision is made, which is inside the agent's loop rather than downstream of it.

The agent-time layer: rules and findings reach the model in the prompt, before the first save.

In practice that means three things for this attack class specifically.

Your rules arrive with more authority than the repository's. VibeDefend installs into the agent as an MCP server plus hooks, which means the policy the model receives is the one your organisation wrote, not the one that happened to be checked into the folder. A repository file asking the agent to read ~/.aws/credentials is now arguing against a rule that arrived first.

The guard fires on the action, not on the diff. Hooks evaluate the tool call before it runs. Reading a credentials file, piping an environment dump into curl, invoking a tool whose description changed since yesterday: these are decisions the agent makes mid-session, and they are the only place a control can still say no.

The findings are in the loop, not in a dashboard. The agent has live access to what our scanners found across code, dependencies, secrets, infrastructure and pipelines, so when it proposes a change it is reasoning about the current security state of the repository instead of guessing. That is also what lets it notice that the pipeline it was just asked to modify runs on fork events with write permissions.

None of that removes the need for the eight controls. It changes what happens in the gap they cannot close, which is the ninety seconds between a folder being opened and a secret leaving the building.

Frequently asked questions

Can a Markdown file really execute code?

Not by itself, and that is what makes it effective. The Markdown supplies instructions; the agent supplies execution. If the agent has shell access and auto-approve enabled, an instruction file is functionally a script whose interpreter is the model. The one case where the file is closer to literal execution is a settings file that declares hooks, which is what made CVE-2025-59536 a remote code execution issue in Claude Code before 1.0.111.

Is it safe to commit an AGENTS.md or CLAUDE.md to my repository?

Yes, and you should. The risk is not in having one, it is in nobody owning it. Put the file under CODEOWNERS with a security reviewer, require review on changes, and audit for nested copies deeper in the tree. An unreviewed instruction file is the problem; a reviewed one is documentation that also happens to configure your agents.

Does the trust dialog protect me?

It gates the directory, not the content. Anthropic stated this position explicitly when closing the Hookify report: once the directory trust dialog is accepted, project-level configuration under .claude/, including CLAUDE.md, project hooks and plugin rule files, is intentionally loaded. Accepting the dialog is you vouching for the instruction files, not the vendor validating them.

Which files should I put under mandatory review?

At minimum: AGENTS.md, CLAUDE.md, GEMINI.md, .clinerules, .cursorrules, and the directories .cursor/, .claude/, .windsurf/ and .github/copilot-instructions.md. Add any MCP configuration file and any SKILL.md in the tree. Then run a recursive search, because the nested copies are the ones that get missed.

Can I detect instruction file injection with grep?

Partially, and it is worth doing. Search for HTML comments in Markdown, for zero-width and bidirectional Unicode characters, for base64 blobs, and for the verbs that matter: credentials, ~/.aws, ~/.kube, curl, env, export. What grep cannot judge is intent, because the effective payloads read as ordinary project conventions. In the Hookify research, five payloads framed as innocuous conventions were enough to trigger secret leakage.

Does this affect Copilot and Cursor too, or just Claude Code?

All of them. The mechanism is architectural, not vendor-specific: every mainstream agent has a repository-level instruction convention, and every one of them loads it as trusted project guidance. We cover the per-agent specifics in the guides for Claude Code, Cursor, GitHub Copilot, OpenAI Codex and Windsurf.

How is this different from slopsquatting or a malicious package?

Slopsquatting exploits a hallucinated dependency name so that an install pulls attacker code, which we explained in what is slopsquatting. Instruction file injection needs no install and no registry. It changes what the agent is trying to do, rather than what code ends up in the tree, which is why dependency scanning is structurally blind to it.

What should I do first if I think an agent followed a poisoned instruction file?

Treat it as a credential incident, not a code incident. Rotate anything the agent could read: cloud keys, kubeconfig, provider tokens, anything in the environment. Then pull the agent's session transcript and read the tool calls in order, because that is your only reliable record of what actually executed. Only after that look at the diff, since in the documented cases no code was modified at all.

Live · just shipped

Install VibeDefend in 5 seconds.

One command wires every coding agent on your machine to CybeDefend: your business rules, your compliance frameworks, and guards that block destructive calls before they fire.

Install in 5 secondsNode 18.17+
npx -y @cybedefend/vibedefend@latest install
Auto-detects
  • Claude CodeClaude Code
  • CursorCursor
  • OpenAI CodexOpenAI Codex
  • WindsurfWindsurf
  • GitHub CopilotVS Code Copilot
Read the README on npm