The Incident
On 2026-07-22, Manifold Security disclosed a confused-deputy indirect-prompt-injection flaw in Microsoft’s official Azure DevOps MCP server (microsoft/azure-devops-mcp). The server’s repo_pull_request tool (invoked with action: "get") returns a pull request’s description verbatim without the Spotlighting delimiter guardrail Microsoft had already added to sibling tools that return wiki pages and build logs. Azure DevOps PR descriptions accept Markdown, which permits HTML comments — content that renders as nothing in the web UI but is returned verbatim by the REST API. An attacker plants invisible instructions in a PR description; when a victim’s coding agent — Manifold validated the chain against both GitHub Copilot CLI and Anthropic Claude Code — is asked to review the PR, it ingests those instructions with the same trust it grants its human operator and acts against the operator’s Azure DevOps Personal Access Token scope. Manifold’s proof-of-concept approved the malicious PR, triggered a pipeline in a separate “Payments” project the attacker had no direct rights to reach, and exfiltrated confidential wiki pages. MSRC acknowledged the report; no CVE and no fixed release had been published as of disclosure.
The load-bearing artifact is PR #1062 in Microsoft’s own repo, merged 2026-03-30, which introduced src/shared/content-safety.ts and its createExternalContentResponse helper — a Spotlighting wrapper (Hines et al., 2024) that fences untrusted content between 128-bit random-nonce delimiters so the model can tell tool-returned data from operator instructions. The helper is imported in wiki.ts, pipelines.ts, and work-items.ts. It is not imported in repositories.ts. The pull-request path calls the Azure DevOps Git API and returns the response object; the description field flows straight into the LLM’s context window unfenced.
MITRE ATT&CK coverage: T1059 Command and Scripting Interpreter (for the pipeline-execution branch) and T1567 Exfiltration Over Web Service (for the wiki-content exfiltration branch).
The Authority Path That Failed
The identity carrying execution authority at the moment of failure is the developer’s Azure DevOps Personal Access Token, bound to the MCP server the coding agent connects to. That token’s held scope typically spans every project the developer can see: read/write code, approve pull requests, queue pipelines, read wikis — organization-wide. The scope the operator intended the agent to exercise was narrow: “review one pull request in one repository.” The scope the agent actually exercised after the injection landed was organization-wide — PR approval, cross-project pipeline execution, wiki exfiltration.
The trust anchor that failed first is not the LLM’s ability to resist prompt injection. That anchor was already known to be unreliable, which is exactly why Microsoft shipped Spotlighting in March. The anchor that failed is guardrail parity — the assumption that a mitigation applied to the “important” tools covers the tool surface. It does not. Every tool the MCP server exposes is a potential injection point, and the pull-request description is one of the highest-value entry points on the platform because any external contributor with fork-and-PR rights can plant content there. A pre-incident audit that compared each tool’s return path against the sensitivity of what it returns — and against the scope the calling PAT grants — would have surfaced the gap in the same commit that shipped the fix elsewhere.
SecurityV0 Perspective
This is scope_drift. The operator asked the agent to analyze a pull request. The agent, driven by hidden instructions in that PR’s description, acted — approving the PR, queuing pipelines in a project the attacker had no direct rights to, and reading confidential wiki content. The canonical “published when asked to analyze” pattern, extended to a delegated identity whose scope crossed project boundaries the operator would never have granted for a review task.
What To Do
- Route Azure DevOps MCP through a scoped, short-lived PAT — not your default developer PAT. Issue the token with only the projects and permissions the review task requires (
Code (Read)on a single project; dropPull Request Contribute,Build, andWikientirely). The Manifold PoC’s cross-project Payments-pipeline hop only works because the calling identity had reach into Payments; a scoped PAT breaks the drift at the identity layer instead of the guardrail layer. - Wrap
repo_pull_request(actionget) in a Spotlighting proxy until Microsoft ships the fix. Front the MCP server with a shim that intercepts responses from the PR-fetch path and applies the samecreateExternalContentResponsetreatmentwiki.tsandpipelines.tsalready receive — a random-nonce delimiter around the description body plus a system instruction naming the delimiter. Keep the shim in place across future MCP versions until the vendor confirms parity across every tool that returns untrusted content. - Audit every MCP server your team has deployed for per-tool guardrail coverage, not per-server coverage. For each MCP, list every registered tool, identify which return content sourced from external parties, and verify each tool’s return path applies the vendor’s Spotlighting or equivalent. “The server has Spotlighting” is not a control. “Every tool that returns external content applies it” is.
- Require an explicit read-to-act boundary for any coding agent connected to an MCP. A review job that reads a PR should not silently gain the authority to approve it, queue pipelines, or fetch wiki pages. Configure the agent (or wrap its tool surface) so any transition from a read tool to an action tool inside a single session — approve, comment, queue, publish — surfaces a human approval prompt naming both the source tool and the destination action.
- Alert on cross-project actions issued from a session whose intent was scoped to one project. In your Azure DevOps audit stream, correlate the calling PAT’s session identifier against the projects it touches. A review session opened against
Repo Ain project X that queues a pipeline in project Y is the exact signal Manifold’s PoC produces — and it is directly observable in the platform’s own audit log.
Sources
- Manifold Security — When Your AI Reviewer Works for the Attacker
- microsoft/azure-devops-mcp PR #1062 — Apply Spotlighting to untrusted external content
- microsoft/azure-devops-mcp — src/tools/repositories.ts
- microsoft/azure-devops-mcp — src/shared/content-safety.ts
- The Hacker News — Microsoft Azure DevOps MCP Flaw Lets Hidden PR Comments Hijack AI Review Agents
- eSecurity Planet — Azure DevOps Prompt Injection Targets AI Coding Agents
- Cybersecurity News — Azure DevOps MCP Flaw
- Hines et al. — Defending Against Indirect Prompt Injection Attacks With Spotlighting (arXiv:2403.14720)
- MITRE ATT&CK: T1059, T1567