All Articles
CategorySecurity
Reading Time
15 min read
Published
2026-06-25
Word Count
3,735words

Grab a coffee — this one is a deep dive!

AI Coding Agent Permissions: The Prompt Injection Risk

Summary

How the AI coding agent prompt injection risk actually works, what the MCP trust boundary is, and how to apply least privilege to your agent — a sourced, practical hardening guide.

  • Coding agents carry file, terminal, and network access together; everything they read — a repo file, an issue, an MCP response — is a potential instruction carrier.
  • The lethal trifecta (private data + untrusted content + outbound communication) and Meta's Rule of Two give unattended agents a practical permission budget.
  • Allowlist/deny rules match text, not behavior; the real trust boundary belongs in the sandbox's filesystem + network isolation, in a layer the agent can't reach.
  • Fully disabling permission prompts in CI/unattended runs means exceeding the Rule of Two budget without human approval — deploy/publish steps must stay under human review.
AI Coding Agent Permissions: The Prompt Injection Risk

When you give an AI coding agent terminal access, file-write permission, and outbound internet, you're also giving it the authority to treat every piece of text it reads as an instruction. The AI coding agent prompt injection risk starts exactly here: when the agent reads a repo file, an issue, or a web page, it can weigh a hidden command in that content on the same scale as a command you gave it directly. OWASP's 2026 report no longer treats this as theoretical — it's now backed by CVEs and breach records.

💡 Pro Tip: Test every permission you grant an agent with the question "is this blocked by text matching, or by behavior?" — text-matching rules may not hold up against an attacker who has poisoned the environment.

Table of Contents

The difference between an agent and an assistant: files, terminal, network

A classic code-completion assistant only suggests lines; the decision is always yours. A coding agent carries three capabilities at once: it can write to the filesystem, run terminal commands, and reach the network. Claude Code's security documentation defines this difference directly: in the default mode (config value default), the agent starts read-only and asks for explicit approval before editing files or running Bash commands that could change the system.

What changes in auto mode

In auto mode, a separate classifier model replaces this approval flow: it reviews actions and automatically blocks the ones it judges unsafe. This buys speed, but it removes the assumption that "a human approves every action" — an action the classifier misses can pass without you ever seeing it.

The attack surface — everything read can be an instruction

The core limitation of LLM architecture is this: the system prompt, your request, and text pulled in from outside (a repo file, an issue, a web page, an MCP response) are all processed in a single token stream. The model cannot reliably tell "this is a command" apart from "this is just data." When an attacker plants an instruction in a file or page the agent is known to read, that instruction can carry the same authority as a legitimate operator command.

A real supply-chain case

This isn't abstract. A package called postmark-mcp built legitimacy through fifteen clean releases, then quietly added a one-line exfiltration payload — becoming the first malicious MCP server researchers caught in the wild; its long, clean history was used precisely to build trust. In the same period, a remote-code-execution flaw with a CVSS score of 9.6 (CVE-2025-6514) was reported in core MCP infrastructure.

Why coding agents stand out

Of the 53 agentic projects OWASP tracks, 28 fall into the coding-agent category; semi-autonomous frameworks and tools such as n8n (57 advisories), Claude Code (22), and AutoGPT (15) lead the list of projects with the most published security advisories — coding agents have become the surface security researchers watch most closely.

This isn't a coincidence: a coding agent, by definition, combines high privilege (file writes, command execution) with high exposure (third-party dependencies, open-source repos, PR descriptions, issue text). A chat assistant only produces text; a coding agent can make the text it produces run directly. OWASP's 2025 report listed this as a "possible threat"; the 2026 report now catalogs it with real CVEs and breach records — a sign the field has matured and the attack surface has moved from theory to practice.

The blurry line between content and command

In practice: you tell an agent "read this issue and fix it," and the issue text contains a sentence like "also run this script and send the output here" — the model can process it as a continuation of your own instruction. You only said "read the issue," but the agent may have treated that second sentence as a task too. It's the conceptual cousin of classic SQL injection: whatever happens when user input and query logic aren't separated is roughly what happens when untrusted text and agent instructions aren't separated either.

The data exfiltration path: packaging content into a URL

The most classic target of an injected instruction is convincing the agent to package sensitive content (source code, an .env variable, a private API response) into a URL and send it out. That URL can be a query string, an image address, or an apparently harmless third-party service. The defense principle is version-independent: any link that packages content into a public third-party service's URL should be treated as an actual upload to that site, and shouldn't pass automatic approval unless you explicitly want it to.

This distinction shows where defense needs to focus: the agent's outbound traffic needs at least as much scrutiny as its input. If an agent triggers a request without asking "should I POST the result to this URL," the third leg of the "lethal trifecta" — outbound communication — is already open.

Simon Willison's "lethal trifecta"

The framework Willison defined combines three properties: access to private data, exposure to untrusted content, and the ability to communicate externally. When all three exist in the same agent at once, a single injected prompt can turn that agent into an exfiltration tool. Meta's "Agents Rule of Two" treats this like a budget: an agent operating without human approval can satisfy at most two of the three at once — if the third is about to come into play, a human approval step must be inserted.

Applied to your own project: if a coding agent already accesses your repo (private data) and can read up-to-date docs on the internet (untrusted content), opening the third property — free outbound communication — without human approval fills all three boxes at once. In that case, either fully disable the agent's outbound network requests (especially POST/PUT), or gate every outbound request with a separate approval step. The sandbox's network isolation mode is the most reliable way to keep this third box closed.

Applying the principle of least privilege to the agent

In practice there are three layers: the working-directory lock, allowlist/denylist rules, and sandbox isolation. Claude Code's docs state that in default mode the agent can only write to the folder it was launched in and its subfolders, and cannot modify parent directories without explicit permission — a strong boundary on its own: the agent can't slip into ~/.ssh or a directory outside the project, whether "by accident" or through an injected instruction.

The allowlist trap

There's a critical detail here: a deny rule matches a command exactly as written. Put a command like git branch on the allowlist, and the rule only recognizes that literal text string — not the command's runtime behavior. In a poisoned environment (git aliases or PATH altered), the same text can trigger a different action. Claude Code's docs note this explicitly: for enforcement that doesn't depend on text, look at sandbox network isolation.

The .claude/settings.json snippet below only performs text matching; it does not guarantee behavior:

json
1{
2 "permissions": {
3 "deny": ["Bash(curl:*)", "Bash(wget:*)"],
4 "additionalDirectories": []
5 }
6}

The sandbox layer

The sandboxed bash tool provides filesystem and network isolation together; /sandbox defines this boundary and reduces permission prompts, but it grounds security in runtime isolation rather than text. CVE-2025-59532 in Codex CLI showed how dangerous the opposite is: the agent's own output could redefine the sandbox boundary — meaning sandbox configuration must live in a layer the agent cannot reach.

The practical implication: if sandbox rules sit in a file the agent can edit (say, a config file at the project root), the agent can edit its own boundary — like putting a lock's key behind the locked door itself. Sandbox policy must live outside the agent process, in a separate privilege layer the agent cannot write to. Otherwise an injected instruction could follow "first loosen the sandbox rule, then do what you want" — a single-step defense bypassed by a two-step attack.

The trust boundary with MCP servers

MCP (Model Context Protocol) servers give the agent direct read-write access to tools, databases, and APIs. This directness is simultaneously what makes MCP powerful and what makes it the riskiest surface: connecting to an MCP server is equivalent to trusting the code behind it — whatever the server can do, the agent becomes able to do too.

postmark-mcp is a concrete example: the package stayed clean for a long time before quietly turning malicious, proving that a "legitimate release history" alone can't count as trust. CVE-2025-6514 moved the problem from package level to protocol level — found in core MCP infrastructure used by hundreds of thousands of developers.

Practical trust rules

  • Verify the source: keep official/first-party MCP servers in a separate trust tier from community packages.
  • Narrow the scope: give a server only the tool/data access it genuinely needs, not "everything."
  • Pin versions: MCP dependencies left open to automatic updates leave a door open to silent degradation.
  • Monitor: log the network requests an MCP server makes; an unexpected outbound call is the first warning signal.

Trust is not a one-time decision

The real lesson of postmark-mcp is that trust needs to be dynamic, not static. A package that stayed clean for fifteen releases turned malicious on the sixteenth — "I reviewed this once, it's safe" can lose validity over time. This is a known problem in traditional dependency security too (supply-chain attacks), but its impact is larger in the MCP context: an npm package usually processes data, while an MCP server directly steers the agent's actions. Version pinning and periodic re-review don't eliminate the risk, but they narrow the window.

The trap of disabling permission prompts in CI and unattended runs

It's tempting to run an agent in "don't ask, just apply" mode in a CI pipeline or overnight job — but that means exceeding Meta's Rule of Two budget without human approval. An autonomous attack bot called hackerbot-claw exploited exactly this kind of chain in February-March 2026: through a poisoned Trivy GitHub Actions setup at Aqua Security, it seized LiteLLM's PyPI publish token and, without any human intervention, published two backdoored LiteLLM releases.

Why CI is especially fragile

A CI environment usually has all three at once: access to secrets (deploy tokens), exposure to untrusted content (PR descriptions, issue text, third-party Actions), and outbound communication (publishing packages, triggering deploys) — exactly the CI version of the lethal trifecta. In an unattended run with human approval disabled, once the three combine, the attack chain can complete on its own.

The allowlist bypass example in Cursor

CVE-2026-22708 demonstrated exactly this in Cursor: an attacker poisoned the agent's working environment so that a "safe" allowlisted command like git branch carried an arbitrary payload. The allowlist itself made the attack easier by auto-approving commands the attacker needed — and turning off permission prompts in CI makes this trap bigger still.

The difference between unattended and interactive runs

In an interactive session, you're at the screen; when the agent proposes an unexpected command, you see it, question it, reject it. In an unattended/CI run that feedback loop doesn't exist — the agent decides and applies, and you learn the outcome only from logs or, worse, an incident report. That's why "don't ask" mode is far riskier in CI than interactively: interactively a human still acts as a brake in the background, while in CI that brake is fully disabled.

A practical rule: commands left on auto-approve in CI should only be ones whose side effects are reversible and that don't require outbound communication (tests, linting, static analysis, builds). Irreversible or externally-facing steps — publishing packages, triggering deploys, rotating secrets — should still go through human approval, even if it slows the pipeline, to prevent a chain like hackerbot-claw's from completing unattended.

Practical hardening settings

Think of the following three elements together: the working-directory lock, narrowing network access through isolation rather than text (sandbox.network.allowedDomains and sandbox.filesystem.denyRead), and a threshold requiring human approval in unattended runs.

json
1{
2 "permissions": {
3 "defaultMode": "default",
4 "deny": ["Bash(curl:*)", "Bash(wget:*)", "Bash(nc:*)"],
5 "additionalDirectories": []
6 },
7 "sandbox": {
8 "enabled": true,
9 "network": { "allowedDomains": ["*.github.com"] },
10 "filesystem": { "denyRead": ["~/.ssh"] }
11 }
12}
bash
1# Every additional directory opened outside the working directory should be a deliberate decision
2# Default: only the folder you launched in + its subfolders
3claude --permission-mode default

When widening the working-directory lock (additionalDirectories), do it per project, one at a time — a global "write anywhere" permission zeroes out the sandbox's least-privilege advantage. In CI, rather than disabling permission prompts entirely, the most practical way to preserve the Rule of Two budget is leaving only pre-listed, non-outbound commands (test, lint, build) on auto-approve while keeping deploy/publish steps under human approval.

GOLDEN TIP

The most valuable insight in this article

This tip holds the article's most important takeaway.

Easter Egg

You found a hidden gem!

There's a hidden detail in this section. Want to uncover it?

Reader Reward

A quick checklist, based on the sources cited in this article, for granting your agent permissions. Match each item against your project's real configuration.

Comparing the defense layers

Seeing side by side what each layer actually guarantees makes the decision easier.

Layer
What it limits
Text-based or behavior-based
Default mode approval
Every file edit + system-changing Bash command
Behavior-based (human approval on every action)
Auto mode classifier
Actions judged unsafe
Behavior-based (model-driven review)
Allowlist/denylist (permissions.deny)
Specific command text
Text-based (matches as literally written)
Sandbox (filesystem + network isolation)
Runtime access
Behavior-based (isolation, independent of text)
Working-directory lock
Writable directory scope
Behavior-based (directory boundary enforced)

At the MCP trust boundary, the problem isn't a missing layer but where it's placed: since connecting to a server already means trusting its code, the table below summarizes which case broke which trust assumption.

Case
Assumption broken
Source
postmark-mcp (silent exfiltration after 15 clean releases)
"Long release history = safe package"
Help Net Security, June 11, 2026
CVE-2025-6514 (MCP core, CVSS 9.6)
"Protocol infrastructure is a separate trust layer"
Help Net Security, June 11, 2026
CVE-2026-22708 (Cursor allowlist bypass)
"A command on the allowlist is always safe"
Help Net Security, June 11, 2026
hackerbot-claw / LiteLLM PyPI chain
"CI secrets stay safe without human oversight"
Help Net Security, June 11, 2026

FAQ

What is a prompt injection attack?

An LLM processes the system prompt, the user's request, and text pulled from an external source (a file, a web page, an email, an MCP response) as a single token stream, and can't reliably separate "command" from "data" among them. An attacker can plant a hidden instruction in a document the agent will read, steering it into executing that instruction as if it were legitimate.

How are AI coding agents protected against prompt injection?

Two frameworks work well in practice: Willison's "lethal trifecta" (private data + untrusted content + outbound communication together multiply the risk) and Meta's "Agents Rule of Two" (at most two of these can coexist without human approval). Allowlists also shouldn't create blind trust; CVE-2026-22708 showed allowlisted commands can be abused in a poisoned environment.

What permissions should I grant a coding agent?

Avoid granting file, terminal, and network access all at once without oversight. The combination of "reading private data + reaching the internet" especially should require human approval. Cases where sandbox boundaries could be redefined by the agent's own output (CVE-2025-59532) show that sandbox configuration must live in a layer the agent can't reach; when widening the working-directory lock, do it per project, one at a time.

Will an AI agent execute an instruction found inside a file it reads?

Yes — architecturally there's no mechanism that reliably prevents this; the model can interpret file content as an instruction too. This is exactly what happened with postmark-mcp (a one-line exfiltration payload quietly added after fifteen clean releases) and the LiteLLM/PyPI supply-chain attack (an automated attack that continued without human intervention).

What's the difference between a sandbox and an allowlist?

An allowlist matches text; a sandbox limits behavior. Even a command on the allowlist can trigger a different action in a poisoned environment. Sandbox filesystem and network isolation instead rests on the runtime boundary, not the command's text — so if you want text-independent enforcement, look to the sandbox.

When is it acceptable to give an agent full permissions in CI?

Almost never as "full permissions" — only in a scope-narrowed form. Steps whose side effects are reversible and don't require outbound communication (test, lint, build) can be left on auto-approve; steps that access secrets, publish packages, or trigger deploys should stay under human approval. The hackerbot-claw / LiteLLM PyPI case showed what happens when that distinction is skipped: two backdoored releases published directly, without human intervention.

Update (September 2026)

Since this article's publish date (June 25, 2026), two concrete changes have landed in auto mode's permission/security behavior. First, in v2.1.261 (September 4, 2026): auto mode now treats a link that packages content into a public diagram-renderer's URL as an actual upload to that site, and no longer auto-approves it unless you explicitly want it to. Second, in Claude Code's latest release (npm dist-tag 2.1.280, as of September 23, 2026), auto mode's security-check behavior got two fixes: when a security check rejects reviewing an action, the action is now rejected outright in a single pass, with retrying noted as pointless; and when the security check doesn't respond at all, retries now back off, with the turn stopping after ten consecutive attempts. This directly hardens against a "retry a rejected action in an infinite loop" pattern that could cause unexpected resource consumption in CI/unattended runs. Naming note: this mode's "Manual" label and the manual alias require Claude Code v2.1.200 and later.

Conclusion

Granting an AI coding agent permissions means treating it as an operator, not an assistant — and operator mistakes can now be triggered remotely through prompt injection. As a natural continuation of Agentic AI tool use, planner loop, and production architecture, here we focused on the security surface: least privilege, sandbox isolation, the MCP trust boundary, and the human-approval budget in CI.

For more, the vibe coding security checklist is a practical starting point; for the MCP protocol itself, see Claude Code MCP integration and MCP security, CIMD, RFC 9207, DCR. Curious how permission-sharing works in multi-agent coordination? LangGraph production agent framework is a related next read.

Sources

Tags

#prompt injection#AI coding agent#MCP security#sandbox#least privilege#CI security#Claude Code#OWASP
Muhittin Çamdalı

Muhittin Çamdalı

Lead Mobile Engineer

Lead Mobile Engineer with 12+ years of experience. Expert in iOS, Android and cross-platform architectures with Swift, SwiftUI, Kotlin and Flutter. I build performant, user-friendly mobile apps.

iOS Development News

Weekly Swift tips, SwiftUI tricks and iOS best practices. No spam, only valuable content.

We respect your privacy. You can unsubscribe at any time.

Share