SecurityPrompt injection: why we limit what our AI agents are allowed to do
In short: Adversa AI describes a prompt injection in which the instruction sits on a web page as ciphertext. The agent decrypts it itself and follows it, while a text filter sees only noise. With Copilot CLI one fetched link was enough to pull a
.env.prodfile in 28 seconds. What decides the outcome is the rights the agent holds. On our side, access to the tools is restricted, and we have not measured any filter for outgoing web requests on the agent host. The post ends with a ten-minute check for your own agent.
Anyone who lets an AI agent read a web page hands the author of that page a share of the order book. That is not new, but in summer and autumn 2026 the security firm Adversa AI showed that a text filter no longer closes this path. This post sums up what Adversa and Ars Technica document, then describes what we have on record about our own agents and what we measured on 5 November. Much of it is incomplete, and we say where.
Prompt injection is an attack in which an AI agent treats text from an untrusted source, such as a web page, a mail or a tool output, as an order from the user and carries it out. How much damage follows depends on the agent's rights: everything it may read, run and send out, an attacker can use as well.
What Adversa and Ars Technica document
Adversa calls the method Cryptographic Context Injection. The instruction sits on the page as AES-256-GCM ciphertext, next to the key material and a request to decrypt it with Python. A plaintext filter cannot read the content, because that would take running the decryption. The agent runs it in its own code environment, and the result shows up as the output of its own program. There, according to Adversa, it is no longer handled as foreign input. For Copilot CLI, Adversa reports that the same instructions in plaintext were refused. Ars Technica summarizes on 20 August that language models cannot fix the root of prompt injection, so vendors build guardrails that the next attack goes around. That is the author's assessment.
Three cases follow.
With Grok (report of 20 August), a request to summarize a page makes the agent, according to Adversa, build a supposed key that actually holds the user's name, location, plan and chat history, and append it to an attacker's URL. The report to xAI went out on 3 June, and by Adversa's account the follow-ups on 4 and 10 August went unanswered. On 19 August the attack still reproduced.
With Gemini, the decrypted text looks like a Python traceback and tells the model to act on the error message if the code fails. According to Adversa this produced content Gemini normally suppresses and revealed its system instructions. Over the summer the success rate dropped, and the cause is unknown.
With GitHub Copilot CLI (report of 6 October), the user has the agent read a page in autopilot mode. After 28 seconds the contents of a .env.prod are in the attacker's log, and the agent's own summary says something else. Which model handles the session matters: one model ran the chain in 50 percent of the attempts, two others refused. With automatic model selection the user cannot see which one they get. GitHub accepted the finding as valid but did not rate it a vulnerability, because the user had given the agent the page and full permissions.
Adversa sells an agent-security platform. The measurements are the vendor's statements, and we did not reproduce them. A figure like "20 attempts, 40 percent", which we came across in connection with Grok, appears in neither Adversa nor Ars and is not used here.
Five rules, and where we stand
From this Adversa derives five rules for the environment around the agent: process untrusted content in a context without tools and credentials, release outgoing actions only with resolved arguments, record tool calls per session, alert on sequences instead of single texts, and ask vendors how data and instructions are kept apart. We compared these rules with our notes and measurements.
| Adversa rule | What we have on record | Source, date |
|---|---|---|
| Process foreign text without rights | For the mail checker the rule is that a manipulated text may neither silence nor steer the verdict, and a missing verdict never counts as a pass. For the planned inbox in the personal assistant, sanitizing and testing are listed as a precondition. | Notes of 4 October and 17 August |
| Limit outgoing actions | The agents' mail goes only to three addresses from a list that lives on the host, out of the agent's reach. For web requests no egress filter is documented. | Note of 17 September, measurement below |
| Record tool calls | Prompts that pass through the LiteLLM gateway are stored in Postgres. Whether the resolved tool arguments of every session are in there, we have not checked. | Note of 7 August |
| Alert on sequences | Nothing in our records. | As of 5 November |
| Ask vendors about separation | Open, we have no list. | As of 5 November |
The filter in the gateway matches patterns. A note from October records that it blocked the phrase "Ignore previous instructions" and let "Ignore all previous instructions" through. In August it turned out that six of six organic hits were false alarms, for example a skill catalog with the word "jailbreak" in a description. A hit in a tool result stayed in the session for good and killed it. Writing patterns for imperatives instead of vocabulary causes less trouble, but against encrypted text a pattern match does not help, going by Adversa's description.
What we measured on 5 November
We measured read-only, with iptables -S over SSH, on 5 November 2026 at 20:06 UTC, on two Linux hosts: the host for LibreChat, LiteLLM and the MCP sidecars, and the host for the dsh agent.
| Measurement | Result | Unit | Measurement host |
|---|---|---|---|
| Gate in front of the seven dsh sidecars | 1 rule: everything except the agent host is dropped | rules | sidecar host, chain DOCKER-USER |
| Gate in front of the LiteLLM port | 17 allowed sources, everything else logged and dropped according to the script | sources | same host |
| Gate in front of the crawl sidecar | 6 allowed sources | sources | same host |
| Egress filter on the agent host | chain DOCKER-USER empty, OUTPUT on ACCEPT | rules | agent host |
A comment in the gateway's script records that the LiteLLM port and the crawl sidecar were open without authentication to the whole LAN until the audit of 26 October. The gate was set after that audit and protects the entrances. It says nothing about the question "where may the agent send data when a page it has read tells it to?", and that is exactly what the attack targets. On the agent host we found no filter for outgoing connections. Whether a proxy or a rule inside the container sits in between, we did not investigate.
On rights, according to our notes: the Proxmox MCP token was not read-only when we checked on 3 August: it held rights to create, delete, stop and roll back VMs on all nodes. The note records the PVEAuditor role as the fix. The operator profile in the MCP server only gates at application level, and the token sets the boundary. A later note on the Telegram agent lists the same token. Whether it has been replaced since, we did not check for this post. For the dsh agent, a note of 5 October records that the container has the fleet's root SSH keys mounted, and the agent CLI has run as root on the host since 29 September. Both were recorded as open decisions on 5 October.
Still to measure
We did not measure three things for this post. We name the method, there is no result yet.
- Outgoing traffic of the agent: on the agent host look at
ip route, proxy variables in the container and rules inFORWARDandDOCKER-FORWARD, then have a person send a single request from the container to a test server of our own and count it in the test server's log. The agent itself gets no task for this. - Rights of the Proxmox token: query
GET /access/permissionswith the token for every path and compare against the write privileges, as described in the note of 3 August. - Traces per session: read the field
proxy_server_requestof a dsh session inLiteLLM_SpendLogsand check whether tool calls with resolved arguments are in it. According to our note the fieldmessagesstays empty there.
We will not replay an attack with an encrypted instruction against our agents.
The ten-minute check
- List every agent that reads web pages, mails or tickets (two minutes).
- Next to each, write which keys, files and networks the same agent can reach (three minutes).
- For every row that has both, remove one right: separate the reading or take away the credentials (three minutes).
- Check by hand whether the agent may send data out without asking, and write down the result (two minutes).
For the implementation, our work on AI on your own hardware can help. The earlier history of this attack class is in Agentjacking: when the error message hijacks the AI agent, and more posts on the subject are collected under Security and data protection.
What is documented and what is open
Documented, because we read the sources on 5 November: the structure of the method, the three cases with their report dates, the 28 seconds, the 50 percent for one Copilot model and GitHub's position, all as statements by Adversa, and for Grok additionally put in context by Ars Technica (we could only read its header section). Documented by our own measurement of 5 November: the gate rules and the missing egress filter on the agent host.
Open: whether xAI, Google and GitHub have changed anything since the reports, whether Adversa's figures can be reproduced independently, and the three points under "Still to measure".
Further Reading
Sources last checked: 2026-11-05
- Adversa AI: GitHub Copilot CLI vulnerability, Cryptographic Context Injection steals developer secrets, 6 October 2026; vendor report with disclosure timeline.
- Adversa AI: Zero-click Grok data theft, 20 August 2026; method, Grok and Gemini cases.
- Ars Technica: Grok exfiltrates user data when malicious instructions are encrypted, 20 August 2026; independent assessment by Dan Goodin.
- Logos: GitHub Copilot, Simple Icons 16.36.0 (MIT per icon data, trademark: GitHub).
What did Adversa AI show against Copilot CLI?+
According to Adversa, GitHub Copilot CLI in autopilot mode reads the file .env.prod after fetching a prepared web page and sends its contents to an attacker, in 28 seconds and without asking. It depends on the model: one model ran the chain in 50 percent of the runs, two others refused. GitHub did not classify the finding as a vulnerability. These are Adversa's statements, we did not reproduce the attack.
Does a filter help against prompt injection?+
Only partly. Our own filter in LiteLLM blocked the phrase Ignore previous instructions, according to a note from October, but let Ignore all previous instructions through. Adversa also describes that encrypted text never triggers a text filter in the first place. Filters stay useful as an extra layer, the limit is set by the agent's rights.
What is the first step for a mid-sized company?+
Keep a list: which agent reads text from outside, and which credentials does the same agent hold? Where both meet, separate the reading or the rights. The ten-minute check at the end of this post walks through it.
senn-tech