Prompt injection in 2026: from theoretical warning to documented exploit class
OWASP ranks prompt injection the #1 LLM risk. 2026 gave it a paper trail: Unit 42's documented cases and a flaw in Microsoft's Azure DevOps MCP server prove it.
By Gabriel Lara, Developer Relations, Norbelys
Founder-reviewed ·How we research and correct articles
Prompt injection has sat at the top of OWASP’s Top 10 for LLM Applications as LLM01 since the list’s first edition. What changed in 2026 wasn’t the ranking — it’s that the entry stopped being a hypothetical. Independent researchers have now documented indirect prompt injection happening against production systems in the wild, and a disclosed vulnerability in a major vendor’s own AI-agent tooling showed the exact mechanics end to end. If you’re building anything on top of an agent that can read content and call tools, this is no longer a “someday” risk to plan around.
What actually moved this year
In March 2026, Palo Alto Networks’ Unit 42 published documented cases of web-based indirect prompt injection observed in the wild — instructions embedded in ordinary web content (a page, a comment, metadata) that an AI agent picks up and executes while doing something unrelated, like summarizing a page or researching a topic. That’s the distinction that matters: indirect injection doesn’t require an attacker to talk to your agent directly. It only requires your agent to read something an attacker controls, somewhere in its normal workflow.
Four months later, that abstract description got a concrete, well-documented instance. Security researchers at Manifold Security disclosed a flaw in Microsoft’s official Azure DevOps MCP server: one of its tools returned pull-request descriptions verbatim, including Markdown-rendered HTML comments that display as nothing in the web UI but are still present in the raw content an AI agent receives. An attacker with access to a single project could hide instructions in an invisible comment. A reviewer’s AI coding agent, asked to summarize or review that pull request, would read the hidden instructions as part of the content and act on them — approving PRs, triggering pipelines in unrelated projects, extracting confidential wiki pages — all under the reviewer’s own legitimate credentials. The agent did nothing outside its documented capabilities. It was simply fed an instruction it had no way to distinguish from the content it was asked to process.
Why this is structurally hard to patch away
Traditional injection attacks (SQL injection, XSS) have a clean fix: separate code from data, so a data field can never be interpreted as an instruction. Prompt injection doesn’t have that clean separation available, because the entire interface is natural language — there’s no reliable syntactic marker that distinguishes “the user’s instruction” from “a sentence embedded in a document the agent happens to be reading.” A model can be trained to be more skeptical of embedded instructions, and system-level guardrails can filter obvious patterns, but neither closes the gap completely. That’s why the practical mitigations that work aren’t about making the model injection-proof — they’re about limiting what an injected instruction can actually accomplish even if it succeeds.
Mitigations that hold up in practice
What actually reduces the blast radius of a successful injection
Treat everything the agent reads as untrusted input
A pull request description, a scraped web page, an email body, a support ticket — anything the agent processes that didn't come directly from an authenticated user should be handled with the same suspicion as unsanitized user input in a traditional application.
Scope credentials to the narrowest task, not the broadest role
The Azure DevOps incident worked specifically because the agent inherited the reviewer's full permissions. An agent that can only act within the scope of the single task it's running would have had nothing to escalate into.
Require human confirmation before consequential actions
Reading and summarizing content is low-risk. Approving a change, sending an email, moving money, or deleting a record is not. Put a confirmation step between an agent's read access and any action with a real-world consequence, especially one that's hard to reverse.
Log what the agent read, not just what it did
When an agent takes an unexpected action, the log entry that says what happened is far less useful than the one that shows what content it was processing when it decided to do it. That's the difference between debugging the incident and re-running it blind.
Assume any tool returning unsanitized content is a live injection surface
If a tool call returns raw text an agent will reason over — a document body, an API response, a webpage — check specifically for this pattern rather than assuming the platform vendor already closed it everywhere.
The takeaway for anyone shipping an agent with tool access
None of this is a reason to avoid giving agents access to tools and outside content — that access is the entire value proposition. It’s a reason to build the same way you’d build any system that processes untrusted input with real permissions attached: least privilege by default, a confirmation gate on anything consequential, and logging detailed enough to reconstruct what happened when something goes wrong. If you’re issuing API credentials to any agent that calls into your own systems, scoping those keys to least privilege is the same discipline applied at the API layer, and it’s worth doing regardless of which model or agent framework is on the other end of the connection — authenticating any server-to-server integration the same way you would a human-driven one is the baseline this whole risk class argues for.
What this looks like on Norbelys specifically
Norbelys ships a public MCP server at mcp.norbelys.com/mcp so an agent can draft copy, check deliverability, or manage a sending program on a tenant’s behalf — which means the same confused-deputy shape described above is a real design constraint, not a hypothetical. Every call that server receives is authenticated by whatever credential the agent is holding, so a scoped, dedicated key rather than a shared admin one is the first mitigation, exactly as the least-privilege habit above describes. The second is structural: sending is the one action in an outreach workflow that isn’t reversible, which is why an AI operator working on a sending domain hits rate limits and an explicit approval gate enforced by the platform before anything reaches a real inbox, rather than a limit the agent’s own instructions are trusted to respect. An injected instruction can still try to talk an agent into sending early — it just can’t skip the gate that isn’t inside the agent’s control to begin with.