A developer asked AWS's agentic IDE, Kiro, to summarize a web page. That single, ordinary request was enough to get remote code execution on their machine.

Researchers at Intezer, working with Kodem Security, found the chain. They hid an instruction inside an API documentation page using text set to color:#fff;font-size:1px, invisible to a human, plainly readable to Kiro. The instruction told the agent to register a new Model Context Protocol server and point its start command at attacker-controlled code. Kiro read the page, followed the hidden instruction, rewrote its own ~/.kiro/settings/mcp.json, reloaded it automatically, and launched the rogue server. No approval step ever stood in the way. AWS has patched the issue. No CVE was assigned.

Where the security model actually broke

Kiro's safety design depends on a human clicking "allow" before anything risky happens. That is a reasonable design if the only actions a human needs to review are the ones the human initiates. The flaw here is that the developer only approved one thing: fetching a URL. Everything downstream, reading the hidden text, deciding to write a new server entry, rewriting the config file, reloading it, and executing the resulting command, happened inside the agent's own reasoning, where no approval gate existed.

Kiro did sometimes show a popup saying the MCP configuration had changed. It made no difference. The file reloaded regardless of what the developer clicked. The only real control on the page was cosmetic.

This is not a one-off Kiro bug

The same shape of failure has now shown up in Kiro three separate times over about a year:

  • July 2025 โ€” Johann Rehberger (Embrace The Red) showed prompt injection writing to mcp.json on release day, plus a second route through .vscode/settings.json to allowlist shell commands.
  • Cymulate's finding โ€” Kiro auto-executed code written to .vscode/tasks.json on folder open. AWS assigned CVE-2026-10591 for this one, scoring 8.8 on CVSS 3.1.
  • February 2026 โ€” Intezer's mcp.json chain, confirmed live on 0.9.2 (macOS) and 0.10.16 (Ubuntu), patched in 0.11.130.

Three researchers, three angles, one underlying pattern: an agent that can edit the files controlling what it is allowed to execute will eventually be talked into editing them by something other than the developer. Cursor and Copilot are not exempt either. A December 2025 survey catalogued more than 30 comparable flaws across AI coding tools, all converging on the same mechanism: legitimate editor features turned into prompt-injection paths to code execution or data theft.

AWS's actual fix says the quiet part out loud. Kiro now marks mcp.json, .vscode/tasks.json, .git, and other sensitive paths as protected, each requiring explicit approval before any write, enforced by the platform in both Autopilot and Supervised mode. Kiro's own docs now state it directly: "Supervised mode is a code review workflow, not a security control." That line is the whole lesson. A model that reviews its own actions is not a security boundary. A model that asks the user to review actions the platform never actually blocks is not one either. The control has to live somewhere the model's reasoning cannot touch it, and it has to hold regardless of what the model was convinced to do.

Why this keeps happening to agents specifically

Traditional software has a fixed set of inputs and a fixed set of things it will do with them. An LLM-driven agent does not. It reads whatever text lands in its context window, whether that text came from the developer, from a fetched web page, from a tool's output, or from a file it opened, and treats all of it as material to reason over. A one-pixel white string on a documentation page is indistinguishable, at the token level, from an actual instruction from the developer. That is the entire attack surface: get text in front of the model, phrase it like an instruction, and let the model's own capabilities (writing files, running shell commands, fetching URLs) do the rest.

This is structurally the same failure as the SQL injection era, except the "query language" here is unrestricted natural language, and the "database" is a general-purpose coding agent with filesystem and process privileges. You cannot patch this away by making the model smarter at spotting injected instructions. Non-determinism is the point: Intezer noted their own proof of concept did not fire every time, the model sometimes just summarized the page like it was asked. That is not a defense, it is a coin flip, and an attacker only needs to win once.

Why the fix has to sit in front of the model

AWS's own remediation is the answer, generalized: enforcement has to happen outside anything the model can be told to change, on every request, in every mode, regardless of what instructions the model absorbed. That is precisely the job of a firewall that sits between the LLM and the outside world rather than inside the agent's own judgment.

Milgram is built as a personal LLM firewall for exactly this boundary. It inspects AI traffic in both directions in real time, looking for the two failure modes that turned Kiro's page-summarization feature into a remote-code-execution channel:

  • Hostile prompt injection. Instructions smuggled into fetched content, whether hidden in invisible text, encoded in a document, or buried in tool output, get flagged and filtered before they can pass as legitimate instructions to the agent's decision-making.
  • Data exfiltration and malicious instruction attempts. When a compromised agent tries to act on an injected instruction, whether that is writing to a sensitive config path, phoning home with system data, or exfiltrating credentials, Milgram measures and catches that attempt at the traffic layer, independent of whether the agent itself was fooled.

The distinction that matters is where the check lives. Kiro's original design put the check inside the same reasoning process an attacker was trying to manipulate. That is why the popup asking for approval did nothing: the model had already decided, and the "control" was downstream of the compromise, not upstream of it. A firewall inspecting traffic before it reaches the agent's execution layer, and before the agent's output leaves the boundary, does not depend on the model correctly recognizing that it has been manipulated. It does not care whether the injected text was clever enough to fool a non-deterministic model on a given run. It applies the same inspection every time, in every mode, which is the exact property AWS had to bolt onto Kiro after three rounds of researchers found the same hole.

What to take from this if you are shipping agentic tools

Every team wiring an LLM agent into shell access, file writes, or arbitrary tool execution should assume the agent will, at some point, ingest attacker-controlled text and treat it as an instruction. The question is not whether that happens. It is what stands between that moment and actual code running with a developer's privileges. If the answer is "the model's own judgment, backstopped by a popup," the Kiro history says exactly how that goes. If the answer is enforcement at the traffic boundary that holds regardless of what the model was told, you have a real control. That is the gap Milgram is built to close, and it is why an LLM firewall is not an optional add-on for anyone shipping AI agents with real-world privileges, it is the boundary the model itself can never be trusted to hold on its own.