The agent trusted the punctuation
Agent Data Injection, a proof-of-concept from Seoul National University, UIUC, and Largosoft posted in July 2026, does not hide instructions in a prompt. It forges the punctuation an agent uses to tell a trusted field from untrusted text — a curly quote, an escaped quote, even a stray dollar sign — so an attacker's GitHub comment reads as the maintainer's own fix and a faked CI record reads as a clean build. It slipped purpose-built prompt-injection defenses up to half the time across GPT-5.2, Claude, and Gemini. Bromure Agentic Coding normalizes the forged delimiters before the text becomes a plan, gates the run-this and merge-this actions that reach outside the box, and runs the whole thing on a disposable Linux VM with decoy credentials.
Your coding agent decides which text to obey by reading the punctuation around it — the quotes and braces that say "this part is the maintainer, that part is a stranger's comment." A new attack forges that punctuation. It does not write a cleverer instruction. It writes a curly quote, and the stranger's comment starts wearing the maintainer's name.
On July 6, 2026, researchers at Seoul National University, the University of Illinois Urbana-Champaign, and Largosoft — led by Woohyuk Choi and Professor Byoungyoung Lee — posted a paper with a blunt title: Agent Data Injection Attacks are Realistic Threats to AI Agents. It describes a class of attack, Agent Data Injection (ADI), that sits next to prompt injection rather than inside it, and that slipped purpose-built injection defenses up to half the time where classical prompt injection scored near zero. OpenAI, Google, and Anthropic confirmed it works. No fixes were reported at publication.
The reason it matters to anyone running a coding agent is that it attacks a thing the agent cannot help but trust: the boundary between the data it fetched and the structure that data arrived in.
The delimiter is the security boundary
An agent's context is a pile of text from many sources — your instructions, a file, a web page, a comment someone left on an issue. To act sensibly, the model has to keep track of which piece is which: this is the maintainer's name, that is the body of a comment a stranger wrote. It does that the only way text allows — with punctuation. Quotes and braces, tags, brackets, line breaks. The delimiters mark where a trusted field ends and untrusted content begins.
A strict parser treats those delimiters literally: a quote is a quote, and a character in the middle of a comment is just a character. A language model does not. It reads the punctuation, in the paper's framing, by guesswork — it infers structure from what the characters look like they mean. And that is the whole opening. An attacker who controls a low-trust field — a product review, a GitHub issue comment, a line in a file — sprinkles punctuation-like characters into it, and the model reads structure that was never there.
The unsettling detail is how little craft it takes. The researchers call the technique probabilistic delimiter injection, and they found the fake punctuation "does not even have to be right." An escaped quote, a curly quote, even a stray dollar sign passed for a real field boundary and fooled the model. A strict parser would have read every one of those as ordinary text.
What it does to a coding agent
The web-agent version of ADI is easy to picture: forge the identifier on a page element and an agent shopping for you clicks "Buy Now" where it meant to click "Read More." The version aimed at developers is worse, because the trusted field it forges is who said the code was safe.
In one demonstration, an attacker leaves a comment on a GitHub issue and forges the author attribution so the agent reads it as coming from the project maintainer. When a developer later asks the agent to "apply the maintainer's fix," Claude Code, OpenAI's Codex, and Google's Gemini CLI do exactly that — they run the attacker's command, because as far as the model can tell the maintainer asked for it. In another, a malicious pull request fakes the record of its own completed CI checks. The agent sees a clean build in its context, judges the code safe on that fabricated evidence, and merges actual malware.
Across the six models the team tested — GPT-5.2, GPT-5-mini, Claude Opus 4.5 and Sonnet 4.5, Gemini 3 Pro and Flash — the numbers are not a rounding error. Structured data yielded a 31–43% success rate; web-page data ran from 33% all the way to 100%. And against defenses built specifically to stop prompt injection, ADI still got through up to half the time, where the same defenses stopped classical injection cold. Two mitigations worked in the lab and both cost something: tagging page elements with random, unguessable IDs (as ChatGPT's Atlas browser does) cut success from about 49% to 29%, and strict data-provenance tracking drove attacks to zero — while dropping the agent's ability to finish normal tasks to about a third.
Why the usual filter misses it
A prompt-injection filter is trained to notice instructions hiding in data — "ignore your previous directions," "run this command," the recognizable shape of a command dressed up as content. ADI does not need that shape. The malicious text can read like an ordinary maintainer note. What carries the attack is the punctuation around it, and a filter reading for suspicious language sails right past a curly quote. That is why the paper's own working defense was not a smarter classifier but a stricter parser — provenance that refuses to guess where a field ends.
This is the same lesson the rest of agentic security keeps relearning. A command denylist loses to the shell that rewrites the command. A trusted MCP tool hands back data an attacker wrote. A workspace you trusted launches servers you didn't. ADI is the version where the poisoned thing is not the instruction and not even the data, but the frame — the delimiter that tells the agent which text to believe. You cannot pattern-match your way out of a curly quote.
Where Bromure draws the line
Bromure Agentic Coding does not try to make the model a better guesser about where a field ends. It does two things the model can't, and then makes sure that when both are wrong the damage lands somewhere disposable.
First, the forged delimiters get normalized before the text becomes a plan.
Bromure's on-device prompt-injection detection is not only a local model that
reads for intent; it is paired with a deterministic scanner — the same one that
catches invisible-Unicode and homoglyph tricks. Curly quotes fold to straight
quotes, confusable and zero-width characters get stripped, and a field whose
delimiters don't match the canonical structure gets flagged. That is the
strict-parser instinct the researchers found defeats ADI, run as one
layer on the untrusted text the agent fetched — the same class of input as a
rogue CLAUDE.md or a poisoned comment — and all of it stays on your Mac.
Second, the two actions ADI actually wants still stop at a boundary. Look at what the attack is trying to trigger: run the maintainer's fix and merge the pull request. Both are actions that reach past the agent's sandbox — a shell command, a push to a remote. Every agent Bromure runs — Claude Code, Codex, Grok Build — runs inside a disposable Linux VM, and the steps that leave that box are the ones Bromure surfaces for confirmation. A forged attribution does not get to auto-run a command, and a faked CI record does not get to auto-merge a branch, because "the maintainer said so" is the judgment the confirmation step exists to double-check.
Third, if a command does run, it runs in a box you throw away. Suppose a delimiter is novel enough to slip the normalizer and convincing enough to pass review. The command executes inside the VM. Reset the profile to base and whatever it dropped — a script, an SSH key, a scheduled job — is gone. Nothing it did survives the window closing.
Fourth, there are no real credentials for it to take. A "fix" that scrapes
the environment and disk for tokens finds Bromure's decoys — synthetic
AWS keys, a throwaway ~/.kube/config, placeholder git and registry tokens
(brm_…). The real secrets are swapped in only on the host, in the proxy, on
the way out to the genuine API. Whatever the command ships off-box is a bag of
strings that authenticate to nothing, and the connection that ships it shows up
in the Security Log as outbound traffic you can see.
What this draws a line around
Normalization and confirmation are containment, not a cure for a model that reads structure by guesswork. It is worth being exact about what Bromure changes and what it does not.
The comment still gets planted
Bromure does not stop an attacker from leaving a forged GitHub comment or faking a CI record, and it does not fix the underlying fact that a language model infers where a field ends. Those are the model's and the platform's to solve. What Bromure changes is what happens after the agent reads the forged text: it gets normalized, and the actions it tries to trigger get checked.
Normalization is a net, not a wall
Folding curly quotes, stripping confusables, and flagging mismatched delimiters catches the ADI tricks the researchers demonstrated and more, but a novel delimiter can be phrased to slip a single scanner. Treat it as one layer; the disposable box with decoy keys and a logged egress is what holds when the scanner misses.
Confirmation guards the boundary, not every edit
The confirm step earns its place on actions that leave the box — running a command, pushing, merging. A forged instruction that only edits a file inside the VM is caught by isolation and decoys, not by the prompt. Keep the boundary actions gated; that is where a faked "maintainer said so" is worth a second look.
Substitution covers the secrets you configure
The decoy swap protects credentials you put in a profile: model keys, git and cloud tokens, registry and cluster tokens, SSH keys. A token a script writes to disk mid-run, or a session you open by hand inside the box, is just data. Keep secrets in the broker, not in the workspace.
The researchers' point is not that six models share one bug. It is that the way an agent tells a trusted field from untrusted content — punctuation it reads by guesswork — is the same everywhere an agent meets the outside world, and it is not getting fixed this quarter. Today the forged delimiter lives in a GitHub comment. Tomorrow it is a Jira field, a commit trailer, a header on a fetched page. Your agent is going to read a boundary an attacker drew, and up to half the time it will believe it. The question is not whether the punctuation ever fools it. The question is what runs when it does: your machine, your real tokens, and a command that pushed itself to main — or a disposable Linux box that normalized the quote first, held the merge for a look, and had nothing but decoys inside. Bromure makes it the second one.