HOW-TO GUIDE | AI SECURITY
13 min read

AI Coding Tools as Attack Surface: When Config Files Backdoor Your Codebase

A concrete detection and CI hardening guide for the rules-file, instruction-file, and MCP config poisoning vector documented against Cursor and GitHub Copilot

3
Distinct invisible Unicode techniques (zero-width joiners, bidirectional overrides, Unicode Tags block codepoints) Pillar Security documented hiding instructions in .cursor/rules and Copilot instruction files
Feb 26 to Mar 12, 2025
Window in which Pillar Security disclosed the Rules File Backdoor technique to Cursor and then GitHub
May 1, 2025
Date GitHub shipped a hidden-Unicode-character warning, over seven weeks after the initial disclosure; Cursor's stated position that this is the user's responsibility has not changed
2
Cursor CVEs (CVE-2025-54135 and CVE-2025-54136) patched in version 1.3.9 after researchers showed a new mcp.json file could be written and executed via indirect prompt injection without the approval prompt shown for edits

SponsoredHorizon3.ai

Proactive Security for the AI Era

NodeZero continuously and autonomously pentests infrastructure, identity, cloud, and now web applications, chaining weaknesses across every domain the way real attackers do. Every finding ships with replayable proof showing exploitable business impact, not theoretical risk.

See NodeZero WebApp in action

Every AI coding assistant reads more than the code you ask it to change. Cursor loads .cursorrules or its .cursor/rules/*.mdc successor on every session. Claude Code loads CLAUDE.md. GitHub Copilot loads .github/copilot-instructions.md. A growing set of tools loads a shared AGENTS.md, and nearly all of them load an MCP server configuration such as mcp.json to know which external tools they are allowed to call. None of that content goes through the review process your team applies to application code. It is treated as trusted context the moment the assistant starts, and that is exactly what makes it a target.

In March 2025, Pillar Security disclosed a technique it named the Rules File Backdoor: hiding adversarial instructions inside .cursor/rules and GitHub Copilot instruction files using invisible Unicode characters, zero-width joiners, bidirectional text override markers, and codepoints from the Unicode Tags block, that render as blank space in every editor, terminal, and diff viewer a human would use to review the change, while still being parsed as text by the model's tokenizer. Because the poisoned file lives in the repository itself, it survives forking and cloning: every developer who pulls the repo inherits the backdoor along with the code. This is a distinct threat from the topics we have covered elsewhere. Our piece on governing AI coding assistants compares vendor admin controls and data retention policy, and our coverage of agentjacking documents an attacker injecting commands into data an MCP server returns at runtime. This piece is narrower than both: it is about the static configuration files that ship inside your own repositories, arriving via a poisoned dependency, a malicious pull request, or a compromised template, and what a security or platform team can actually build to catch it before merge.

The problem: config files are trusted context, not reviewed code

A pull request that changes application logic gets read by a reviewer who understands what the function is supposed to do. A pull request that changes .cursorrules, CLAUDE.md, or mcp.json usually does not get that scrutiny, because most reviewers do not think of a rules file as executable. It is treated as documentation for a tool, not as an instruction set the tool will silently obey on every future session.

That gap is exactly what the Rules File Backdoor exploits. Pillar Security's proof of concept demonstrated an attacker embedding instructions to insert malicious script tags into generated HTML, add references to external resources without the developer's knowledge, and otherwise steer the assistant's output, all encoded so the reviewer's editor and GitHub's own diff view showed nothing but empty space. When Pillar disclosed the technique to Cursor on February 26, 2025, and to GitHub on March 12, 2025, both vendors initially responded that the risk fell to the user, not the platform: Cursor stated it was not a vulnerability on its side, and GitHub said users are responsible for reviewing and accepting Copilot's suggestions. GitHub did eventually ship a warning for hidden Unicode characters in reviewed content by May 1, 2025, more than seven weeks after the initial report, but Cursor's own position has not changed, and the same invisible-character technique still works against any tool that does not specifically check for it.

The attack surface is not limited to Unicode obfuscation. Cursor's own MCP implementation shipped with two related flaws, tracked as CVE-2025-54135 and CVE-2025-54136 and reported through mid-2026, where creating a brand-new .cursor/mcp.json file did not require the approval prompt that editing an existing one triggers. An attacker who could get the agent to read a poisoned document, a README, an issue, a piece of untrusted content the agent was asked to summarize, could use indirect prompt injection to have the agent write a new mcp.json defining an attacker-controlled server, and that server's commands would run without the user ever seeing an approval dialog. Cursor patched the underlying approval gap in version 1.3.9. The Cloud Security Alliance's March 2026 research note on repository-file instruction hijacking documents a broader pattern in the same family: any file an AI coding agent reads as part of onboarding a repository, not just the ones purpose-built for assistant configuration, can carry instructions the agent will act on.

The files worth treating as part of this attack surface, across the tools most engineering orgs run today, are: .cursorrules and .cursor/rules/*.mdc (Cursor), CLAUDE.md (Claude Code), .github/copilot-instructions.md (GitHub Copilot), AGENTS.md (increasingly read by multiple tools as a shared convention), .windsurfrules (Windsurf), any mcp.json or tool-specific equivalent such as .cursor/mcp.json or .vscode/mcp.json (MCP server definitions for any tool that supports the protocol), and .vscode/settings.json where it configures assistant behavior or MCP servers directly. A poisoned copy of any of these can arrive the same way a poisoned dependency does: through a malicious pull request, a compromised project template a new repo was scaffolded from, or a transitive package that ships one of these files as part of its own scaffolding tooling.

Prerequisites before you build the guardrail

The procedure below assumes a few things are already in place. If they are not, address these first.

Subscribe to unlock Remediation & Mitigation steps

Free subscribers unlock full IOC lists, Sigma detection rules, remediation steps, and every daily briefing.

Free daily briefing

Briefings like this, every morning before 9am.

Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.

The procedure: inventory, detect, gate, and allow-list

This is a numbered sequence. Steps 1 and 2 build visibility into what exists and what a poisoned version looks like. Steps 3 through 5 turn that visibility into an enforced control. Step 6 closes the historical gap.

Subscribe to unlock Remediation & Mitigation steps

Free subscribers unlock full IOC lists, Sigma detection rules, remediation steps, and every daily briefing.

Validation: prove the guardrail actually fires

Do not trust the CI job because it exists. Open a real, throwaway test pull request against a non-production repository that adds a CLAUDE.md change containing a zero-width-joiner-obfuscated instruction (a harmless placeholder string, never a real payload) and confirm two things separately: that the CI job's byte-level scan flags it even though the PR's rendered diff in your git host's web UI shows nothing unusual, and that the branch protection rule actually blocks merge until the required CODEOWNERS group approves. Repeat the test with an mcp.json change adding an unpinned, unapproved server entry and confirm the same job fails for that reason independently. If either test PR merges without a block, the control is not doing what you think it is doing, and you should find out in a test repository, not in an incident review after a real one got through.

Failure cases: what this guardrail does not catch

Even a fully implemented version of the procedure above has real gaps that a security team should know about going in.

Subscribe to unlock Remediation & Mitigation steps

Free subscribers unlock full IOC lists, Sigma detection rules, remediation steps, and every daily briefing.

Security tradeoffs: strict allow-listing versus developer friction

None of this is free. Requiring a named security reviewer on every change to a rules or MCP config file adds a review dependency to a class of file developers are used to editing freely and iterating on quickly, and if that review queue becomes a bottleneck, developers will find a way around it, editing the file locally without committing it, or routing configuration through a path the CI job does not yet cover. Strict MCP server allow-listing has the same failure mode: a team that wants to adopt a new MCP server for a legitimate integration and hits a hard CI block with a multi-day approval process will be tempted to hardcode the server call somewhere the gate does not inspect.

The realistic position is to keep the reviewer requirement narrow, scoped only to the specific file paths in step 3, not to all configuration or all code, so the friction lands only where the risk actually is. Keep the MCP allow-list process fast for genuinely new requests (a same-day or next-day turnaround, not a multi-week security review) so teams have no incentive to route around it, and treat a growing allow-list as a sign the process is working, not as scope creep to push back against. Where Cursor and GitHub have both stated this risk is the user's responsibility rather than something their platforms will fix, the tradeoff is not really optional: the organization has to own detection and gating itself, and the only real choice is how much friction to accept in exchange for how much of the documented attack class actually gets caught before merge.

The bottom line

Rules files, instruction files, and MCP configuration files are read by AI coding assistants as trusted context on every session, but they are rarely reviewed with the scrutiny applied to application code, and Pillar Security's Rules File Backdoor research already demonstrated that invisible Unicode characters can hide working instructions inside them that survive a fork. Cursor's own CVE-2025-54135 and CVE-2025-54136 showed the same category of risk extends to MCP server definitions written without an approval prompt. Neither Cursor nor GitHub has committed to closing this at the platform level, which means the control has to live in your own CI pipeline: inventory the files, scan them at the byte level for invisible-character obfuscation and known malicious phrasing, gate changes to them behind a named reviewer and a required CI check, and pin every MCP server source to an explicit, approved version. None of that stops a semantically plausible instruction from passing a distracted reviewer, and none of it reaches an attack delivered at runtime through an already-trusted MCP server's own data, which is a separate control. But it closes the specific, already-documented gap where a poisoned configuration file sitting in your own repository goes completely unreviewed today.

Frequently asked questions

What is a rules file backdoor in an AI coding assistant?

A rules file backdoor is an attack, first documented by Pillar Security in March 2025, that hides adversarial instructions inside AI coding assistant configuration files such as .cursor/rules or GitHub Copilot instruction files using invisible Unicode characters like zero-width joiners and bidirectional text overrides, so the instructions are parsed and obeyed by the model but invisible to a human reviewing the file in a normal editor or diff view.

Which files should a security team treat as part of this AI coding tool attack surface?

The files worth inventorying and gating are .cursorrules and .cursor/rules/*.mdc for Cursor, CLAUDE.md for Claude Code, .github/copilot-instructions.md for GitHub Copilot, the increasingly shared AGENTS.md convention, .windsurfrules for Windsurf, any mcp.json-style MCP server definition, and .vscode/settings.json where it configures assistant or MCP behavior directly.

Did Cursor or GitHub fix the rules file backdoor vulnerability?

Only partially. Cursor told Pillar Security in March 2025 that the risk falls under the user's responsibility and is not a platform vulnerability, and that position has not changed. GitHub initially gave a similar response but shipped a warning for hidden Unicode characters in reviewed content by May 1, 2025, which catches the specific obfuscation technique disclosed but not every possible variant or plain-language instruction hiding in these files.

How is a config file backdoor different from the agentjacking MCP attack?

A config file backdoor poisons a static file that lives inside your own repository and is delivered through a malicious pull request, a compromised template, or a poisoned dependency, so it can be caught by scanning committed files before merge. Agentjacking instead injects malicious instructions into data an already-trusted MCP server returns at query time, which never appears in a committed file and requires a separate runtime control at the agent-MCP boundary rather than a CI file scan.

Can a normal code review or a standard secrets scanner catch a poisoned rules file?

Not reliably. A normal code reviewer is not looking for invisible Unicode characters and typically does not scrutinize configuration files with the same attention given to application logic, and most secrets scanners are tuned to detect credential patterns, not adversarial natural-language instructions or zero-width obfuscation. Catching this requires a dedicated byte-level and pattern-based scan built specifically for these file types.

What is the first concrete step to defend against AI coding tool config file backdoors?

Start with an inventory of every .cursorrules, .cursor/rules, CLAUDE.md, AGENTS.md, copilot-instructions.md, and mcp.json-style file across every repository your engineering org maintains, since you cannot scan, gate, or review paths you have not identified, then add CODEOWNERS review requirements and a CI check on exactly those paths before building out the broader allow-listing and historical re-scan steps.

Sources & references

  1. Pillar Security: New Vulnerability in GitHub Copilot and Cursor (Rules File Backdoor)
  2. The Hacker News: New 'Rules File Backdoor' Attack Lets Hackers Inject Malicious Code via AI Code Editors
  3. Security Affairs: Rules File Backdoor, AI Code Editors Exploited for Silent Supply Chain Attacks
  4. Cloud Security Alliance Labs: README Injection, Repository Files Hijacking AI Coding Assistants
  5. The Hacker News: Critical Cursor Flaws Could Let Prompt Injection Escape Sandbox and Run Commands
  6. CSO Online: Sandbox Bypass Flaws in Cursor IDE Highlight Prompt Injection as an RCE Vector

Free resources

25
Free download

Critical CVE Reference Card 2025–2026

25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.

No spam. Unsubscribe anytime.

Free download

Ransomware Incident Response Playbook

Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.

No spam. Unsubscribe anytime.

Free newsletter

Get threat intel before your inbox does.

50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.

Unsubscribe anytime. We never sell your data.

Eric Bang
Author

Founder & Cybersecurity Evangelist, Decryption Digest

Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.

Giveaway: InfoSec World 2026 All Access Pass ($3,895 value)

Details →
Daily Briefing

Subscribe to enter the giveaway

Every subscriber is automatically entered. You also get daily threat intel every morning: zero-days, ransomware, and nation-state campaigns. Free. No spam.

Already subscribed? You're already entered.

Giveaway

Win a $3,895 InfoSec World 2026 pass.