Safeguard
AI Security

Prompt injection in AI coding assistant system prompts

Copilot, Cursor, and Windsurf all read untrusted repo text into the same channel as trusted instructions — three 2025 CVEs show what happens next.

Safeguard Research Team
Research
6 min read

On June 29, 2025, a researcher reported to Microsoft that GitHub Copilot's Visual Studio Code extension could be tricked into executing arbitrary shell commands just by opening a file. The flaw, tracked as CVE-2025-53773 and disclosed by Embrace The Red, worked by hiding an instruction inside a README or source file that told Copilot to write "chat.tools.autoApprove": true into the workspace's .vscode/settings.json — flipping the editor into "YOLO mode," where every subsequent tool call runs without confirmation. About a month later, AIM Security and Check Point Research independently disclosed a pair of Cursor IDE flaws, CVE-2025-54135 ("CurXecute," CVSS 8.6) and CVE-2025-54136 ("MCPoison"), both fixed in Cursor 1.3 on July 29, 2025. All three bugs share one root cause: the assistant reads attacker-reachable text — a README, a Slack message, an MCP config file — into the exact same context window as the user's and developer's trusted instructions, with no reliable way for the model to tell them apart. This piece walks through what those disclosures show, and what a hardened agent system prompt has to do differently.

What makes AI coding assistants a distinct prompt-injection target?

AI coding assistants are a distinct target because they combine two things most chatbots don't: broad ambient tool access (shell, filesystem, git, MCP servers) and a constant diet of attacker-reachable text. A chatbot answering questions reads mostly what the user types. Copilot, Cursor, Windsurf, Zed's agent mode, Roo Code, Cline, and JetBrains' Junie all routinely ingest READMEs, code comments, filenames, issue bodies, and tool outputs — any of which can be authored by someone other than the developer sitting at the keyboard. Once that content lands in context, the model has no cryptographic or structural signal distinguishing "this is a developer instruction" from "this is text I was asked to summarize." OWASP's agentic-security guidance documents this exact pattern: hidden instructions embedded in an imported rules or "skill" file can redirect an agent into calling a tool that exfiltrates sensitive local data, such as an SSH key, to an attacker-controlled destination — not because the model was jailbroken, but because it correctly followed an instruction it had no reason to distrust.

How did CVE-2025-53773 turn a README into remote code execution?

CVE-2025-53773 turned a README into RCE by exploiting Copilot's own configuration surface as an escalation path. VS Code's Copilot agent, by design, can create and edit workspace files without per-edit approval — edits are written to disk immediately rather than held as a diff for review. An attacker only needed to plant an instruction, potentially hidden with invisible Unicode characters, in any file Copilot might read: a repo README, a source comment, a GitHub issue. When a developer asked Copilot to summarize or refactor that content, the hidden instruction told it to enable autoApprove in workspace settings. From that point, every shell command Copilot's agent mode proposed ran without a confirmation dialog — full command execution with no further user action required. Microsoft shipped a fix in the August 2025 Patch Tuesday cycle. The lesson generalizes past Copilot: any agent whose own trust settings are themselves a writable file inside the workspace has handed attackers a privilege-escalation lever hidden in plain sight.

What did CurXecute and MCPoison reveal about MCP trust boundaries?

CurXecute and MCPoison revealed that Cursor's trust model bound approval to the wrong thing: a config file's existence, not its content. In CurXecute (CVE-2025-54135), a message posted to a Slack channel connected via an MCP server could rewrite Cursor's global ~/.cursor/mcp.json the moment a developer asked the agent to read that channel — and Cursor executed the newly written MCP server command before the developer had a chance to reject the edit, according to AIM Security's disclosure. MCPoison (CVE-2025-54136) was subtler: Check Point Research found that Cursor required approval only the first time an MCP entry was added, then trusted any later edit to that same named entry — so a benign .cursor/mcp.json committed to a shared repo, once approved, could be silently swapped for a reverse shell on a later checkout. Check Point reported the flaw to Cursor on July 16, 2025. Cursor 1.3 (July 29, 2025) fixed both by requiring re-approval on any configuration diff, not just first-time additions.

What common failure pattern connects these disclosures?

The common failure pattern is that trust was granted once, at a coarse grain, and never revisited — while the underlying attack surface stayed writable by untrusted input. Copilot trusted a settings.json flag that a README could flip. Cursor trusted an MCP entry name that its command string could later change under. In neither case did the system distinguish a tool call that reads data from one that executes it, and in neither case was the auto-run configuration itself treated as security-sensitive state requiring the same scrutiny as the code it would go on to run. The pattern isn't unique to Copilot and Cursor — it's a natural consequence of agent architectures where "context" is one undifferentiated stream and "approval" is a one-time gate rather than a standing invariant checked on every execution.

What should a hardened agent system prompt and runtime actually enforce?

A hardened setup treats every piece of tool, file, and MCP output as untrusted data by default — never as instructions — and enforces that boundary in the runtime, not just in prompt wording, since a system prompt alone cannot reliably stop a sufficiently crafted injection. Concretely: require explicit re-approval on any diff to an auto-run or auto-approve configuration, not just its initial creation, so a MCPoison-style silent edit can't ride on a stale trust decision. Separate privilege for read-only tool calls (fetch a URL, read a file, query an MCP resource) from execute calls (run a shell command, write outside the workspace, modify its own settings) so that content ingestion alone can never reach code execution. Declare an explicit allow-list of tool surfaces the agent is expected to use for a given workload, and log every tool call's prompt and response hash so unexpected calls — a shell invocation from a task that should only read files — are flagged rather than silently permitted.

How Safeguard Helps

Safeguard's AI-BOM tracks these exact risk categories for agentic systems built on Safeguard-wrapped models: it annotates which models have jailbreak-resistance tests passing or failing, which input/output filter chains are applied at serving time, and whether tool-use allow-lists are actually enforced rather than merely documented. At inference time, Safeguard retains tool-call logs with prompt and response hashes, validates that each tool call matches a declared tool surface, and scores prompt-injection attempts so an unexpected write to a config file or an out-of-pattern shell call surfaces as a finding instead of a silent trust decision. That combination — declared surface, hashed logs, and injection scoring — is precisely the gap that CVE-2025-53773, CurXecute, and MCPoison exposed: agents whose implicit trust boundaries were never checked against what they actually did next.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.