saturday, september 5, 2026 · the day's ai, attributed published by trilot llc · wyoming
guide · working with ai

Everything your coding agent reads is an instruction

How to run a coding agent against code and documentation you did not write, without letting a paragraph hidden in either one spend your credentials.

Published 2026-09-05 · Updated 2026-09-05 · Read 9 min · Reviewed by Rami Steitieh

Verified 2026-09-05 · Rami
on this page · 0 / 0 checked

You clone a repository you found this morning, point the agent at a vendor’s documentation to wire up a payment library, and tell it to get the build passing. Before it writes a line, it reads a README, a config file, two pages of docs, an issue thread and the output of a package manager. Somewhere in that pile there may be a sentence addressed to the agent rather than to you. It goes into the same context window as your request, in the same font, with no label saying who wrote it.

This guide is about working that way on purpose: what actually happens when an agent reads hostile text, what the vendors have built to catch it, and which settings decide how bad the worst afternoon can be. It is written for the person running a coding agent on their own machine against their own work and their clients’. If you have a security team, a managed fleet and a policy on which repositories may be cloned, you need a threat model document and an approval process, and this is not either of those.

An agent cannot tell your instruction from the text it read

The failure has a name and a standards body. OWASP’s GenAI project defines the category as LLM01, and splits it in two. A direct prompt injection is when “a user’s prompt input directly alters the behavior of the model in unintended or unexpected ways” [7]. The one that matters here is the other kind: indirect prompt injections “occur when an LLM accepts input from external sources, such as websites or files”, and that external content then changes what the model does [7].

The reason this is hard to fix is that there is no channel separation to enforce. Your typed request, the file the agent opened, the page it fetched and the reply from a tool are all tokens in one window. The model can be told to distrust some of them, and it usually does, but it is being asked to make a judgment call about provenance from the content itself, which is exactly what an attacker gets to write.

You can see the assumption in the defences the vendors ship. Claude Code lists “Isolated context windows: Web fetch uses a separate context window to avoid injecting potentially malicious prompts” among its protections [1]. Anthropic’s engineering write-up on auto mode describes the safety classifier as deliberately cut off from the model’s own output: it “sees only user messages and the agent’s tool calls; we strip out Claude’s own messages and tool outputs, making it reasoning-blind by design” [4]. That design exists because tool output is not trusted. Read it the other way round and it is a statement about your session too.

What makes this different from a chatbot being wrong is the tool belt. A coding agent has a shell, a checkout, whatever credentials sit in the environment it launched from, and network access. It does not need to be convinced to do something it would recognise as harmful. It needs to be convinced that one more ordinary developer action is part of the job.

Untrusted text reaches a coding session through ordinary doors

The mental image most people have is a booby-trapped website, which makes the risk feel avoidable. It is not the main door. Untrusted text arrives in a coding session through the same routes as your work: the README and instruction files checked into a repository you just cloned, the source and install scripts of a dependency, the body of an issue or pull request, the output of a command, a vendor’s documentation, and the results a Model Context Protocol server hands back.

The clearest published example is about documentation written for machines. Researcher Alon Hertz’s team looked at llms.txt files, the convention where a company publishes a plain-text map of its own site for AI agents to read: what to install, which endpoints to call, how to get started. They “resolved 8,565 llms.txt files across 6,214 live domains, out of roughly 15,000 companies catalogued” and found “237+ unclaimed artifacts referenced as install or setup instructions”, meaning package names, domains and subdomains that the instructions told an agent to fetch and that nobody had ever registered [8]. The prompt they used was as ordinary as prompts get: build and run a project using a vendor’s documentation, with no link supplied. The agents found the files by themselves.

The researchers registered some of those unclaimed names and put harmless tracking packages there. “The first callback arrived in under four minutes” [8]. One of the unclaimed slots had already been taken by someone else, a package named clerk-next-fix-auth-protection that was “classified under CWE-506: embedded malicious code, flagged by Google’s OSV.dev and Amazon Inspector” and reported to the vendor, who fixed it [8].

Notice what was missing from that attack. No hidden text, no jailbreak, no clever phrasing. A stale line in a real company’s real documentation, served over HTTPS from its own domain, told an agent to install something, and the agent did, because the file looked exactly like what it was: authoritative vendor documentation. Provenance is not trustworthiness. A file being where it should be says nothing about whether the instruction inside it still points somewhere you own.

The same logic applies to the tools you attach. Claude Code’s documentation is direct about where the responsibility sits with MCP servers: Anthropic “reviews connectors against its listing criteria before adding them to the Anthropic Directory, but does not security-audit or manage any MCP server” [1]. Every server you connect is another source of text your agent will treat as a fact.

The defences are real and they are probabilistic

Give the vendors credit for building rather than disclaiming. Claude Code’s security page lists a permission system, a working directory boundary, and trust verification for first-time codebases and new MCP servers, plus two protections it scopes explicitly to Manual mode: command injection detection, where “suspicious bash commands require manual approval even if previously allowlisted”, and fail-closed matching, where “unmatched commands require approval by default” [1]. Commands that fetch content from the web, such as curl and wget, “are not auto-approved by default” [1]. In auto mode, Anthropic runs two things at once: “a separate classifier model reviews actions instead of you and blocks the ones it judges unsafe” [1], and, at the input layer, “a server-side prompt-injection probe scans tool outputs (file reads, web fetches, shell output, external tool responses) before they enter the agent’s context” [4].

Then read the numbers Anthropic published about its own classifier. On a set of real overeager actions it missed 17 per cent of them, and the write-up says so plainly: “The 17% false-negative rate on real overeager actions is the honest number” [4]. The same page states the boundary of the feature: “It is not a drop-in replacement for careful human review on high-stakes infrastructure” [4]. Claude Code’s security page carries the same caveat in bolder terms, warning that while the protections significantly reduce risk, “no system is completely immune to all attacks” [1].

Two more details decide how much of your session the classifier ever sees. On Pro, Max and Team plans, “the built-in starting permission mode is auto mode” [2], so hands-off is where most people begin rather than where they end up. And inside auto mode, “read-only actions and file edits in your working directory are auto-approved”, with everything else routed to the classifier [2]. The classifier sees your messages, “tool calls other than read-only lookups such as file reads and searches, and your CLAUDE.md content”, while “tool results are stripped, so hostile content in a file or web page can’t manipulate it directly” [2]. That is the right trade, and it also means the reviewer of an action never reads the paragraph that motivated it.

The other vendors draw the line in similar places. OpenAI’s Codex documentation says “By default, the agent runs with network access turned off”, and attaches an explicit caution: “Use caution when enabling network access or web search in Codex. Prompt injection can cause the agent to fetch and follow untrusted instructions” [5]. Cursor states that “By default, terminal commands need your approval”, that its tools “only make network requests to: GitHub, Direct link retrieval, Web search providers”, and that “All MCP connections need your approval. After you approve an MCP connection, each tool call still needs individual approval before running” [6].

Decide what the agent can reach, not just what it can do

The durable control is the fourth item on OWASP’s mitigation list, filed under “Enforce privilege control and least privilege access”: “Restrict the model’s access privileges to the minimum necessary for its intended operations” [7]. In practice that is three separate decisions, and they are worth making before you start the session rather than in a dialog box halfway through it.

The first is the filesystem. Claude Code’s working directory boundary means that in Manual mode it can write only to the folder it started in and its subfolders, and asks before reading paths outside that boundary with Read, Grep and Glob [1]. Start the agent in the project, not in your home directory, and do not add directories to widen the boundary because one command failed once.

The second is the network, and it is the one that turns a bad edit into a bad day. Claude Code’s Bash sandbox gives filesystem and network isolation, enforced by the operating system for a command and every process it spawns, and it “pre-allows no domains by default”, prompting the first time a command needs a new one [3]. Keep that list short, and read the warning that comes with it: “Allowing broad domains such as github.com can create paths for data exfiltration”, because the proxy makes its decision from the hostname without inspecting TLS [3]. Codex reaches the same place from the other direction by shipping with network access off [5].

The third is credentials, which is the one people forget because it is invisible. Sandboxed Bash commands “inherit the parent process environment by default, including any credentials set there” [3]. The production database URL exported in the shell you launched from is inside the session whether or not you meant it to be. Launch the agent from a shell that has nothing in it, and keep the .env for anything you cannot afford to lose out of the checkout the agent works in.

One more setting deserves attention because it disappears silently. Claude Code requires trust verification on first-time codebases and new MCP servers, and the documentation notes that “Trust verification is disabled when running non-interactively with the -p flag” [1]. The unattended script is precisely the run with nobody watching, and it is the run where the one prompt that would have made you look at a strange repository does not appear.

calculator
Agent actions nobody read
unreviewed actions / year

Your own volumes. In auto mode, read-only actions and file edits inside the working directory are auto-approved without reaching the classifier [2], so this is the pile with no reviewer at all. Computed in the page; nothing is sent anywhere.

Spend your review on the actions you cannot undo

Approval prompts decay. The first ten get read, the next hundred get clicked, and by the second week the button is just something between you and the work. So decide in advance which actions are worth stopping for, and let the sandbox handle the rest without asking.

Write the irreversible ones down and enforce them as rules rather than intentions. Anything that pushes to a shared branch, publishes a package, runs a migration, sends mail, moves money or deletes rather than archives stays manual permanently. In Claude Code, deny rules are the right instrument because they “block in every mode, including bypassPermissions” [2]. Codex has a blunter equivalent for unfamiliar work: with --ask-for-approval untrusted, “Codex runs only known-safe read operations automatically”, and anything that can mutate state or trigger external execution needs approval [5].

Match the tool to how much you trust the material. Cursor’s own advice for code you have not vetted is not a setting at all: “For untrusted repos, use a basic text editor instead” [6]. Claude Code’s best practices for untrusted content say to review suggested commands before approval, to “avoid piping untrusted content directly to Claude”, and to “use virtual machines (VMs) to run scripts and make tool calls, especially when interacting with external web services” [1].

Then keep one behavioural tripwire. The tell for an injected instruction is rarely dramatic. It is an agent that proposes installing a package nobody mentioned, reaching a domain unrelated to the task, or reading a path outside the project, in the middle of otherwise competent work. Anthropic’s auto mode stops a session and escalates after “3 consecutive denials or 20 total” [4], which is a reasonable count for a machine. Yours should be one.

checklist
Before you point an agent at code you did not write
0 of 8 · saved in this browser only

What still goes wrong

Nothing above detects an attack. It bounds one. The request an injected agent makes is the request you would have made: an install from a public registry, a fetch from a documentation domain, a commit. There is no signature to match and no anomaly to spot, because the anomalous part happened in a context window, upstream of anything that logs. Your realistic detection story is the git history and the audit log of whatever service the agent touched, which is an argument for keeping the agent inside services that keep their own records.

The published numbers are honest and they are also narrow. The 17 per cent false-negative rate comes from a set of 52 cases “curated from sessions where an employee denied the action or it was flagged post-hoc” [4], so it measures the classifier against overeagerness a human had already objected to, and roughly one in six of those still got through. The larger evaluation set, 1,000 data-exfiltration attempts, was generated rather than observed [4]. Both are useful; neither is the attack nobody has written down yet. The isolation has documented edges too. Claude Code’s sandbox does not inspect TLS by default, so its own documentation notes that code inside the sandbox “can potentially use domain fronting or similar techniques to reach hosts outside the allowlist” [3], and warns that with filesystem isolation off, a sandboxed command can write a shell startup file or an executable on $PATH and widen its own access on the next run [3].

The last problem is the one no setting solves. The configuration that is safe and the configuration that is useful pull in opposite directions, and the pull is constant, because every prompt you answer is time and the agent is there to save you time. Cursor’s honest answer for untrusted code is to not use the agent on it [6]. That is available to you too, and it is worth remembering that it is a real option on the days when the repository looks odd and the deadline does not care.

sources
  1. 01Anthropic — Claude Code securitycode.claude.com
  2. 02Anthropic — Claude Code permission modescode.claude.com
  3. 03Anthropic — Configure the sandboxed Bash toolcode.claude.com
  4. 04Anthropic Engineering — How we built auto mode for Claude Codeanthropic.com
  5. 05OpenAI — Codex agent approvals and securitydevelopers.openai.com
  6. 06Cursor — Agent securitycursor.com
  7. 07OWASP GenAI Security Project — LLM01: Prompt Injectiongenai.owasp.org
  8. 08Alon Hertz — Data Became Code: running code inside Fortune 500s using files they published for AI agentsmedium.com
next guide
Getting results from agents that run for hours
10 min · verified 2026-09-05
related guides