GitHub README Prompt Injection: The File Every Coding Agent Reads First
Your coding agents run overnight on cloud dev boxes, with auto-approve on and an organization...
Aug 17, 2026
You can harden an agent against prompt injection in an afternoon. Delimiters around retrieved content. A detector model on the RAG path. A tool allowlist. An approval gate on anything destructive. Every one of those is what a competent team reaches for on day one, because it is what day one offers. Each was also measured against an attacker who had not yet read your configuration.
The UK AISI red-teaming challenge run in the Gray Swan arena put 1.8 million prompt injection attacks against 22 frontier-model agents across 44 deployment scenarios. More than 60,000 produced policy violations. Average attack success was 12.7%, with indirect injection landing at 27.1% against 5.7% for direct. The finding that should change your plan is neither of those. It is that nearly every agent tested produced a policy violation within 10 to 100 queries, and robustness showed almost no correlation with model capability, size, or inference compute. That last result is why the study has not aged out: the frontier has turned over several times since, and the property that failed was never capability.
So the injection lands. A better model does not stop it and a filter written before the attacker arrived does not either. Every step the coerced agent then takes is authorized, which is why IAM boundaries, network policy, and permission checks all return valid while it runs.
What stays under your control is what the agent finishes. The controls that constrain it cannot be switched on today, because they need evidence about your specific agents, and evidence accrues on a wall clock. That interval has a duration and a set of controls that cover it.
Sort your options by what each needs before it can be turned on and they fall into two groups. One inspects text and requires nothing about your agents. The other is derived from a recording of what your agents actually do, and cannot exist before the recording does.
| Control | What it needs before it can be switched on | Time to arm | What skipping it costs |
|---|---|---|---|
| Input filtering and delimiting on retrieved content | Nothing specific to your agents | Same day | Opportunistic payload volume reaches the agent unchecked |
| Tool allowlist per agent | A list of the tools each agent is supposed to hold | Days, gated on engineering answering | Agents keep tools nobody can justify |
| Credential residence change | Knowing which agents hold live credentials | Days to a sprint | A coerced agent inherits every permission the credential carries |
| Rule of Two constraint | A decision about which property gets removed or gated | A sprint, gated on product | Untrusted input, sensitive access, and external write coexist in one session |
| Per-agent behavioral enforcement | A recorded baseline of this agent’s own execution | 7 to 14 days of observation, longer for broad-tool agents | Nothing catches an authorized sequence |
The window in the last row governs the plan. An agent with a narrow task loop converges quickly because its tool and destination set is small: ticket triage against six tools and two destinations settles inside two weeks. A coding agent in a remote development environment produces a wider envelope and keeps moving as the repositories it touches change. Measure your own window rather than inheriting the range, by counting distinct tool-by-destination combinations per day and watching for the plateau.
That gap deserves a name you can use in planning. Observation debt is the interval between an agent reaching production and the point where its own behavior can be used against it. Every agent accrues it the day it ships, you pay it down by watching, and it revolves rather than retiring: a model swap, a new integration, or a framework upgrade reopens part of the balance.
Two shortcuts around the wait exist and they behave differently.
The first is to generate the policy from the deployment manifest, which is deployable this afternoon and describes what you predicted the agent would do. Coercion lives inside what you predicted. The agent calls a tool it was provisioned to call, against a system it is authorized to reach, in a sequence nobody wrote down as forbidden. A declared policy passes every step of that, which is why the baseline has to come from observation.
The second shortcut works. Build the baseline in staging against production-equivalent synthetic traffic, validate it for parity, and deploy the agent already enforcing. Teams running agents where the observation window itself carries regulatory exposure do exactly this, and it is the right call when a fraud detection agent touching cardholder data would otherwise sit unenforced for a fortnight. The cost is parity risk: synthetic traffic that misses production behavior enforces a guess, which is the failure mode observe-first exists to prevent. Run it where exposure justifies the engineering. The rest of the fleet carries the debt.
The first move is not a control. It is the recording, because every control below the filter line consumes it.
Three things have to be true before the clock is usefully running.
You need to know which agents exist. A declared inventory records the agents someone remembered to declare and goes stale on the first deployment that ships without a security review. A runtime-derived inventory reports what is executing.
You need activity attributed to a specific agent. Agent pods restart, autoscale, and get redeployed on model updates, which measures the per-pod observation window in hours. Attribution has to aggregate at the Deployment level to survive the churn.
You need execution telemetry rather than access logs: tool invocations, destinations reached, processes spawned, files opened. An access log tells you a call was permitted. It does not tell you the call was unusual for this agent, which is the only question left once every step is authorized.
Platform engineering will ask what the recording costs before it asks what the recording catches, and that answer decides whether the window survives to week two. Kernel-level collection through eBPF gets most of this without code changes, sidecars, or developer coordination, and ARMO’s sensor runs at 1 to 2.5% CPU and 1% memory.
Interval controls sort on one question: does this control’s return decay when the attacker adapts to it?
Text-side controls decay. A detector on the retrieval path, delimiters around untrusted content, sandwiching that repeats the user instruction after tool output: researchers took eight published defenses of exactly this kind and broke all eight with adaptive attacks at over 50% success. What they still do is remove opportunistic volume, the copy-pasted payloads that make up most of what reaches a public-facing agent. Budget the spend against that volume and assume anything written for your stack passes.
Credential residence does not decay, which makes it the highest-return control available before the baseline arms.
Filtering, delimiting, and sanitizing all operate on text the agent reads. Changing what the agent holds is a different move. An agent carrying a live database credential can complete a read-and-stage chain the moment it is coerced, because the credential is valid and the query is authorized. An agent carrying a dummy key completes nothing against the brokered system, and rewriting the payload does not change that. ARMO’s credential swapping puts agents in the second state without application changes.
Be precise about what that buys, because it is not the whole ceiling. Credential residence bounds what the agent can do with credentials it presents to brokered systems. It does nothing about tools the agent legitimately holds, data already in its context window, code it executes in its own container, or services it reaches laterally inside the cluster. Those are behavioral questions, which is why the baseline still matters after the keys are dummies.
Tool granularity is the next reduction, and it applies where most production agents live: write-scoped agents reading customer-supplied text. Support triage, ticket remediation, inbox automation. Removing the write removes the product, so the reduction happens inside the tool surface. An agent holding a generic HTTP client can reach anything. An agent holding three named endpoint wrappers can reach three things. Same job, smaller completable set. We have previously traced how an over-permitted tool surface turns into API abuse once an agent is redirected.
Rule of Two is for infrastructure agents. Meta’s Agents Rule of Two holds that within a single session an agent should satisfy at most two of three properties: processing untrustworthy input, accessing sensitive systems or private data, changing state or communicating externally. You satisfy it by removing a property or by gating one, which is how Meta’s own worked examples handle it: human confirmation before a stateful action, or fetches restricted to URLs returned by trusted sources rather than URLs the agent composed. Meta positions it as a supplement to least privilege. Either route is deterministic and either costs agent function, so spend it where blast radius justifies the loss. On a cluster remediation agent holding cloud credentials, it does. On a support agent, applying it is how a security program acquires a reputation for breaking production.
Promotion order follows blast radius. The agent holding cloud credentials and Kubernetes API access goes first even if it shipped last, because the same two weeks of observation buys more when spent on the agent that can do the most damage.
That order carries a tension worth naming. High-blast-radius agents have the widest envelopes, so the agents you most want enforced take longest to arm. This is why Rule of Two lives on those agents during the interval: it is deterministic and it does not wait on a baseline. The infrastructure agent gets a hard constraint first and a behavioral boundary later.
Run enforcement in audit before it blocks anything. Audit runs the full enforcement logic and surfaces every deviation it would have acted on, while acting on none of them. That produces a list you can argue with: the tool calls falling outside this agent’s recorded envelope, and the reason each one happened. Expect most to be legitimate: a model update, a new integration, a scheduled job nobody documented. Each explained deviation either widens the baseline or gets flagged, and the rate of unexplained deviations is your signal that the baseline has settled.
Enforce per agent, because normal is per agent. A sales assistant emailing fifty prospects a day and a support responder emailing three escalations a day cannot share a policy: the union of their behavior is useless against the tighter one, and the intersection breaks the looser one. Policies scoped above the individual agent inherit the most permissive agent inside their scope, which is arithmetic rather than a tuning problem, and why enforcement has to resolve to per-agent guardrails.
Three exit criteria move an agent from audit to enforce. The unexplained deviation rate has flattened across a full week that included a deploy. Every deviation in the last window has an owner and an explanation. The rollback path has been exercised once, deliberately, on a non-production replica.
Then hold the pattern open, because the fleet is not static. Agent six ships next quarter into a cluster already enforcing, carrying fresh debt and covered by the same interval controls the first five used, which makes this a standing process rather than a migration.
What promotion produces is the agent’s observed behavior operating as its enforcement boundary. ARMO records that behavior as an Application Profile DNA per agent, and the Audit to Enforce path promotes it into a kernel-level guardrail with no code changes. The full observe-to-enforce progression covers the maturity model this lands in.
Attack success rate is a rate. It prices an opportunistic attempt, which is the number you need to size a filter against inbound volume, and it says nothing about whether an agent is safe to run. The Gray Swan results put policy violations inside 10 to 100 queries for nearly every agent tested, and a payload costs nothing to vary and retry. A metric that converges toward certainty given enough attempts is measuring attacker patience once you use it as a gate.
The same study found almost no correlation between agent robustness and model capability, size, or inference compute. Waiting for a stronger model is not a control.
Three measurements survive as acceptance criteria.
Residual completable capability, stated per agent. Given a coerced instance of this agent right now, name what it can finish: which tables it reads, which endpoints it writes to, which credentials it presents resolve to live secrets, which destinations it reaches. This is the number your interval controls move, and it moves the day you change credential residence rather than the day the baseline settles. It is assembled rather than measured, from declared permissions minus the ones no observation window ever exercised, bounded by what network policy permits. Every input already exists in a cluster running a posture pass over its AI workloads.
Time to detect, measured from the first action outside the recorded envelope. Time to contain, measured from detection to the point the agent can no longer act. Both are exercised rather than estimated: run a coerced agent against your own stack on a replica and time it.
What a CISO signs against is those three, dated, per agent, with the promotion schedule attached. That holds up in an audit where a filter’s published attack success rate does not, because the filter’s number came from a static benchmark and the completable set came from your own cluster.
You cannot buy a control that stops prompt injection from arriving.
You can decide the order. Start the recording first, because every durable control consumes it. Cover the interval with reductions that do not decay: what the agent holds, what its tools can reach, which property an infrastructure agent gives up or gates. Pre-enforce the few agents whose exposure justifies a staging baseline. Promote the rest per agent, in audit, against a baseline from your own cluster. Report the completable set instead of the attack success rate.
Observation debt is the part of this a schedule fixes, and it is the part most rollout plans leave unnamed.
ARMO’s runtime security for AI workloads records each agent’s behavior at the kernel level and enforces against it without code changes. Watch a demo of what audit mode surfaces before an agent is promoted to enforce.
Seven to fourteen days for an agent with a narrow task loop, because its tool and destination set converges quickly. Agents with broad tool access take longer and produce a wider envelope. Rather than accepting the range, count distinct tool-by-destination combinations per day and watch for the plateau: when a week containing a deployment adds no new combinations, the baseline has settled.
For some agents, yes, and it is the right answer where the observation window itself carries regulatory exposure. Build the baseline against production-equivalent synthetic traffic, validate it for parity, and deploy the agent already enforcing. The constraint is parity: if the synthetic traffic misses behavior the agent exhibits in production, you have enforced a guess and you find out through an outage. Narrow-loop agents are far easier to model this way.
Yes, sized to the volume it removes. Filtering strips the opportunistic payloads that make up most of what reaches a public-facing agent, which reduces the number of events anything downstream has to adjudicate, and what it cannot do is carry the load against someone writing for your specific stack. Budget it as a rate reducer and spend the difference on the controls whose return does not decay.
Correlate change against deployment events. Gradual drift that lines up with pod restarts, image updates, and model version changes is organic evolution and should widen the baseline, while sudden shifts with no corresponding infrastructure event are the ones worth alerting on. Agents that genuinely change weekly carry a wider envelope permanently and should carry more of the interval controls as compensation, rather than waiting for a tight baseline that will never arrive. This is a drift classification problem before it is an enforcement one.
Name the debt, then show what has been banked against it. A dated per-agent schedule showing when each baseline arms, paired with the residual completable capability already reduced through credential residence and tool granularity, turns an open-ended wait into a plan with milestones. The position it replaces is a benchmark number with no per-agent evidence and no date on which anything deterministic starts working, which is harder to bring to an audit than a schedule.
Your coding agents run overnight on cloud dev boxes, with auto-approve on and an organization...
Chrome’s agentic mode ships with the most complete public architecture for securing one class of...
The prompt injection 101 most engineers were taught is the chatbot version. It has a...