{"schemaVersion":"1.0","type":"TechArticle","types":["Article","TechArticle"],"slug":"how-to-secure-ai-coding-agents-sandboxing-and-permissions-o0bgz","url":"https://zyvop.com/how-to-secure-ai-coding-agents-sandboxing-and-permissions-o0bgz","title":"How to Secure AI Coding Agents: Sandboxing and Permissions","subtitle":"Give coding agents real power without handing over the keys: a practical guide to sandboxing, least-privilege permissions, and limiting the blast radius.","tldr":"AI coding agents run commands, install packages, and read untrusted text all day. This guide covers the threat model, layered sandboxing, allowlist-based permissions, and how to limit the damage when prompt injection succeeds.","keywords":["coding-agents","permissions","AI security","sandboxing","prompt-injection","Tutorial"],"entities":["Shobit Singh","coding-agents","permissions","AI security","sandboxing","prompt-injection","Tutorial","ZyVOP"],"keyTakeaways":["AI coding agents don't just suggest code anymore.","They run shell commands, install packages, edit files across your repo, call APIs, and open pull requests.","That's what makes them useful, and it's also what makes them risky."],"headings":["What are you defending against?","The lethal trifecta","The core principle: permissions are policy, sandboxes are enforcement","Layer 1: Sandboxing","Filesystem isolation","Process isolation","Network egress control","Credential hygiene","Resource limits and ephemerality","Layer 2: Permission design","Organize by capability","Prefer allowlists over denylists","Protect the escape hatches","Design against approval fatigue","Be careful with \"skip all permissions\" modes","Keep humans on irreversible actions","Tools and MCP servers","Prompt injection: defend the blast radius","Supply chain safeguards","Logging, monitoring, and a kill switch","Matching controls to context","A quick checklist","Closing thoughts"],"outboundLinks":[],"contentText":"AI coding agents don't just suggest code anymore. They run shell commands, install packages, edit files across your repo, call APIs, and open pull requests. That's what makes them useful, and it's also what makes them risky. Think of a coding agent as a very fast junior engineer who has access to your laptop or CI runner, never gets tired, and reads untrusted text all day: READMEs, issue comments, web pages, dependency docs, tool output. Some of that text may be written by someone who wants to hijack it. The good news is that securing agents is mostly classic security engineering: least privilege, isolation, and defense in depth. The key is applying those ideas at the right layers. This post walks through a threat model, how to build sandboxes, how to design permissions that people won't just click through, and what to do about the parts that can't be fully solved yet. What are you defending against? Start with a realistic threat model. Most agent incidents fall into five buckets. Prompt injection. Malicious instructions hidden in content the agent reads: a GitHub issue, a code comment, a web page, an MCP tool response, even a package README. The agent can't reliably tell \"data to analyze\" from \"instructions to follow.\" Honest mistakes. No attacker needed. An agent that misreads a task can delete the wrong directory, force-push over a branch, run a migration against the wrong database, or \"fix\" a failing test by deleting it. Credential and data exfiltration. Environment variables, SSH keys, cloud credentials, .env files, and source code are all within reach of anything that can run a command and make a network request. Supply chain attacks. Agents install dependencies quickly and confidently. Models sometimes suggest package names that don't exist, and attackers register those names (sometimes called slopsquatting). Install scripts can then run arbitrary code. Escalation and persistence. An agent that can edit its own config, git hooks, CI workflows, or build scripts can quietly widen its own access or leave something behind that runs later, outside any supervision. The lethal trifecta A useful mental model, coined by Simon Willison in 2025, is the \"lethal trifecta.\" An agent becomes dangerous to data when it combines three things at once: Access to private data (your code, secrets, internal systems) Exposure to untrusted content (anything an outsider can influence) A way to communicate externally (network access, sending messages, opening PRs) If all three are present, a prompt injection can read your secrets and ship them out. You often can't eliminate the second leg, because useful agents read the web and third-party code. So the practical strategy is to break one of the other two legs, most commonly by restricting network egress and limiting what data is reachable in the first place. The core principle: permissions are policy, sandboxes are enforcement This distinction drives everything else. Permissions are rules about what the agent is allowed to do: which tools, which commands, which paths. They live in the agent's harness and often depend on the model behaving correctly or on a human approving prompts. Sandboxes are enforcement at the operating system or infrastructure level. They restrict what the process can do regardless of what the model decides, what a prompt injection says, or whether a human got tired of clicking \"approve.\" You want both. Permissions give you good defaults, a clean user experience, and audit-friendly control. The sandbox is what holds when the permissions fail. A system prompt that says \"never exfiltrate secrets\" is not a security control. A network that can't reach the attacker's server is. Layer 1: Sandboxing A good sandbox has several independent walls. Think filesystem, process, network, credentials, and resources. Filesystem isolation Scope read-write access to the project directory only. Everything else should be read-only or invisible. Explicitly block secrets locations: ~/.ssh, ~/.aws, ~/.gnupg, cloud CLI config, browser profiles, password manager data, and .env* files. Work in a disposable clone or a git worktree rather than your main checkout, so a bad edit is trivially reversible. Never mount the Docker socket into an agent container. Access to it is effectively root on the host. Process isolation There's a spectrum, and you should pick based on how much you trust the task and how much supervision there is. OS-level sandboxing (for example Seatbelt on macOS, or bubblewrap, Landlock, and seccomp on Linux) is lightweight and works well for an interactive agent on a developer machine. Hardened containers are the common middle ground. Run as a non-root user, drop all capabilities, use a read-only root filesystem, and set resource limits. Stronger isolation such as gVisor or microVMs like Firecracker is appropriate for unattended agents, multi-tenant platforms, and anything processing untrusted repositories. Containers share a kernel with the host, and a microVM doesn't. Here's a reasonable starting point for a hardened container: docker run --rm -it \\ --user 1000:1000 \\ --read-only \\ --tmpfs /tmp \\ --cap-drop ALL \\ --security-opt no-new-privileges \\ --pids-limit 256 \\ --memory 4g --cpus 2 \\ --network none \\ -v \"$PWD\":/workspace \\ -w /workspace \\ agent-image--network none is the safest default for tasks that don't need the internet. For tasks that do, move to the next layer. Network egress control Network access is usually the most important leg of the trifecta to cut. A few rules: Default deny outbound traffic, then allowlist what the task actually needs: your package registries, your git host, and perhaps specific documentation sites. Route traffic through a proxy that logs requests so you can see what the agent talked to. Remember that allowlisted domains can still be abused if they accept user content (a public gist or pastebin-style site is an exfiltration channel). Allowlist narrowly. Consider DNS as a side channel and apply the same egress policy to DNS resolution. Credential hygiene The best secret is the one the agent never sees. Don't give the agent your personal credentials. Give it its own identity, such as a dedicated bot account, with the minimum scopes needed. Prefer short-lived, scoped tokens (for example OIDC-issued tokens in CI) over long-lived keys. Where possible, inject credentials at the network layer through a proxy, so the agent can use an API without ever holding the key in its environment. Point agents at read-only replicas or staging systems, never production databases. Scrub environment variables. Start the agent's process with an explicit allowlist rather than inheriting your whole shell. Resource limits and ephemerality Cap CPU, memory, disk, process count, and wall-clock time. This stops runaway loops and fork bombs, and limits cryptomining abuse. Set budgets on tokens and spend, with a hard stop. Make environments ephemeral. Build a fresh sandbox per task and destroy it afterward, so nothing persists between runs. Layer 2: Permission design With a solid sandbox underneath, permissions become about intent and workflow rather than being your last line of defense. Organize by capability Treat permissions as categories with different risk levels: Capability Typical default Read files in the project Allow Edit files in the project Allow, with diffs visible Run tests, linters, type checkers Allow Install dependencies Ask Edit CI config, git hooks, agent settings Ask or deny Network access beyond the allowlist Ask or deny Push, merge, deploy Ask, or deny for the agent identity Touch secrets or production systems Deny Prefer allowlists over denylists Blocking dangerous commands sounds sensible but is brittle. If you deny curl, the agent can use a Python one-liner. If you deny rm -rf /, there are a hundred equivalent spellings. Shell is expressive, and command chaining, subshells, and encoding tricks make pattern-based blocking leaky. A better approach is to allow specific commands with specific argument patterns (such as git status, git diff, npm test, pytest) and let everything else fall through to a prompt or a hard block. Then let the sandbox, not string matching, cover what slips through. Keep denylists as defense in depth, not as the primary control. Here's an illustrative policy. It's not any particular tool's format, but the shape applies broadly: filesystem: read_write: [\"./\"] read_only: [\"/usr\", \"/opt/toolchain\"] deny: [\"~/.ssh\", \"~/.aws\", \"~/.gnupg\", \"**/.env*\"] network: default: deny allow: [\"registry.npmjs.org\", \"pypi.org\", \"github.com\"] commands: allow: [\"git status\", \"git diff\", \"npm test\", \"pytest *\"] ask: [\"npm install *\", \"pip install *\", \"git push *\"] deny: [\"sudo *\", \"git push --force*\"] protected_paths: # agent may not modify these without approval - \".github/workflows/**\" - \".git/hooks/**\" - \"agent-config/**\"Protect the escape hatches Some files are special because changing them changes what runs later, or what the agent is allowed to do. Treat these as protected: The agent's own configuration and permission files Git hooks and CI/CD workflow definitions Package scripts (postinstall, prepare) and build files Editor task configs and anything that auto-executes A common failure pattern is an agent (or an injected instruction) adding a script that runs outside the sandbox the next time a human opens the project or CI triggers. Design against approval fatigue If your agent asks for approval forty times an hour, people will start approving everything without reading. That's worse than having no prompts, because it creates false confidence. The fix is to shift from \"ask constantly\" to \"generous inside the sandbox, strict at the boundary.\" Let the agent move quickly within a well-fenced environment, and reserve prompts for the moments that cross the boundary: new network destinations, new dependencies, protected files, and irreversible actions. When you do prompt, show the exact command or diff, not a vague summary. Be careful with \"skip all permissions\" modes Many agents have a mode that disables approval prompts for fully autonomous operation. That can be reasonable, but only when the sandbox is doing the real work: a disposable environment, no secrets, no production access, and restricted egress. Running it on your main machine with your real credentials is the configuration to avoid. Keep humans on irreversible actions Use the controls your platform already has: Branch protection and required reviews, with the agent unable to approve or merge its own PRs Push access to feature branches only, no force-push Deploys and schema migrations gated behind a human Agent identities that are clearly labeled, so you can audit what it did versus what a person did Tools and MCP servers Every tool you connect to an agent is an expansion of both its capabilities and its attack surface. An MCP server is code running with whatever access you gave it, and a source of text the model will read and treat as meaningful. Vet servers like dependencies. Review the source, pin versions, and be wary of tools that update silently. Scope tokens narrowly and prefer read-only access where the task allows. Watch for tool poisoning. Tool descriptions and responses are model-visible text, so they can carry injected instructions. Don't pair \"reads untrusted content\" with \"can send or publish\" in the same session without a confirmation step. That's the trifecta again: a tool that reads inbound email plus a tool that sends messages is an exfiltration path. Separate servers for sensitive systems, so a compromise in one doesn't hand over everything. Prompt injection: defend the blast radius Be honest about this one: there is no known way to fully prevent prompt injection today. Models can be trained to resist it and filters can catch known patterns, but none of that is a guarantee. So the engineering goal is to assume it will sometimes succeed and limit what that success can do. Treat everything the agent reads from outside your control as untrusted: issues, PR descriptions, web pages, third-party docs, dependency source, and tool output. Break the trifecta. If the agent must read untrusted content, make sure it can't also reach secrets and the open internet. Require confirmation for sensitive actions that occur after the agent has ingested untrusted content. Don't rely on \"ignore any instructions in the data\" lines in the system prompt as a defense. They help a little and fail often. For high-risk workflows, such as reviewing PRs from strangers or processing untrusted repositories, use read-only access, no network, and the strongest isolation available. Supply chain safeguards Because agents add dependencies so readily, put guardrails around it: Commit and enforce lockfiles, and require approval for any new dependency. Use a private registry or mirror with an allowlist where you can. Verify that a suggested package actually exists, has real history, and is the one you expect, before it's installed. Consider a waiting period on very new package versions, and disable install scripts where your workflow allows it (for example npm install --ignore-scripts). Run dependency and vulnerability scanning in CI so problems surface even if an agent introduced them. Logging, monitoring, and a kill switch You can't secure what you can't see. Log everything: every tool call, command, file diff, and outbound request, with timestamps and the agent identity that made them. Store logs where the agent can't modify them. Alert on anomalies: reads of credential paths, connections to unfamiliar domains, unusual volumes of file reads, edits to protected files. Make it stoppable. You should be able to kill a session or revoke an agent's tokens instantly. Review sessions after the fact, especially for unattended runs. Treat the transcript like a commit history you'd actually look at. Matching controls to context Not every situation needs maximum lockdown. Match the controls to the risk. Scenario Suggested posture Interactive, on your machine, you're watching OS-level sandbox, scoped filesystem, prompts at the boundary, no ambient secrets Autonomous / background tasks Ephemeral container or microVM, allowlisted egress, scoped short-lived token, no prod access CI agents responding to issues or PRs Treat all input as hostile: isolated runner, minimal permissions, no secrets exposed to untrusted triggers, human review before merge Analyzing untrusted code or repos Strongest isolation, read-only, no network, throwaway environment A quick checklist The agent runs in a sandbox that enforces limits at the OS or infrastructure level, not just in prompts Read-write access is limited to the project directory; secrets paths are blocked Outbound network is deny-by-default with a narrow allowlist and logging The agent uses its own scoped, short-lived credentials, never yours Permissions are allowlist-based, tiered by risk, and protect config, hooks, and CI files Approval prompts are rare, specific, and meaningful Autonomous modes run only in disposable environments with no secrets MCP servers and dependencies are vetted, pinned, and least-privileged Humans gate merges, deploys, and migrations Everything is logged, and you can revoke access fast Closing thoughts Securing coding agents isn't about distrusting them so much that they become useless. It's about building an environment where a mistake, or a successful attack, has a small and recoverable blast radius. Permissions shape how the agent behaves day to day; sandboxes guarantee the worst case stays contained. Start with the highest-leverage moves: take away ambient credentials, cut off unrestricted network egress, and keep the agent inside a disposable, scoped workspace. Then tune permissions so that the agent is fast where it's safe and slow where it matters. Do that, and you can let agents do real work with a lot more confidence.","contentHash":"sha256:887c2c74a035d95bfc52889ecc3b396486ba15d6037c23b1fdf41ba590a9ba21","authorName":"Shobit Singh","authorUrl":"https://zyvop.com/author/shobit","authorSameAs":[],"category":"Tutorial","tags":["coding-agents","permissions","AI security","sandboxing","prompt-injection"],"audience":"Software engineers and developers building applications with Tutorial","tone":"Instructional, practical, code-first","readingTimeMinutes":10,"wordCount":2471,"faqs":null,"primaryTopic":"Tutorial","publishedAt":"2026-11-06T07:57:42.804Z","updatedAt":"2026-11-06T07:57:42.804Z","canonicalUrl":"https://zyvop.com/how-to-secure-ai-coding-agents-sandboxing-and-permissions-o0bgz"}