Post

How Much Access Should Your Agent Have?

Alex Garrett-SmithOct 149 min read
How Much Access Should Your Agent Have?

Coding agents can read your files, run commands in your terminal and make network requests, all with exactly the same access you have. GitHub has just made local sandboxing generally available for Copilot (built on Microsoft's new Execution Containers), which makes it a good time to ask how much of that access your agent really needs.

In this guide, we'll look at what's actually at risk, then go through four different ways to limit what your agent can do, from the lightest to the most locked down. Let's dive in.

What can your agent reach right now?

Unless you've set something up, your agent runs commands as you, with access to everything you can access. Here's what that covers.

Your files

Your agent can read every other project on your machine too, along with your dotfiles and your ~/.ssh folder.

Your credentials

Your .env file, cloud provider credentials, package registry tokens and any API keys you've exported in your shell. Basically, anything you can read from your terminal, your agent can read too.

The network

A single curl can send anything the agent has read to any server on the internet. It doesn't need anything special to do this, just access to a terminal.

Your terminal

Everything else you can do from a terminal is fair game too. That includes rm -rf, git push --force, publishing a package and running a migration against whatever database your .env points to.

Why this matters

Most of the time your agent is just trying to help. The problem is that it reads a lot of text you didn't write (issues, READMEs, docs pages, package source code), and any of that text can contain instructions.

Simon Willison calls this the "lethal trifecta". If an agent can access private data, reads content from people you don't trust, and has a way to send data out, someone can trick it into leaking your stuff. A coding agent with full access ticks all three boxes by default.

And this has already happened. In 2025, a compromised npm package went looking for AI coding tools on developers' machines, ran them with their safety checks switched off, and used them to hunt for secrets. Over 2,000 of them ended up in public repos.

None of this means you should stop using agents. You just want to make sure that if something does go wrong, the damage stays inside the project you're working on.

Before anything else: sort out your credentials

Whichever approach you end up choosing, this step applies to all of them. If a production database URL or a live payment key is sitting in your local .env, your agent can read it. So the easiest fix is to not keep them there.

So, give your agent the same kind of access you'd give a new developer on their first day:

  • Test mode API keys rather than live ones.
  • A local or staging database, never production.
  • Fine-grained tokens scoped to the one repo it's working in, with read access wherever possible.
  • Nothing in your shell profile that you wouldn't want printed in a log.

It takes ten minutes to do, and it means that even if everything else below fails, there isn't much worth stealing.

Approach 1: Approval prompts

This is what you get out of the box with most agents. Before the agent runs a command, it asks you, and you approve or deny it.

It's fine when you're sitting there watching. The problem is that after the fortieth prompt you stop reading them and just hit approve, and at that point they're not really protecting you from anything.

Sort commands into three groups

It's much better to let harmless commands run without asking, so you actually read the prompts you do get. Here's how I'd split them.

Commands that only read or can't do lasting damage can run freely. That covers running tests, linting, formatting, git status, git diff and git log.

Anything that changes something outside the project folder or is hard to undo should ask first. That includes installing packages, running migrations, git commit and anything involving rm.

And anything you'd always want to do yourself should never be allowed. For most people that's git push, deploying and publishing packages.

Setting it up

Here's how that looks in VS Code, where true auto-approves a command and false means it always asks:

JSON
{
    "chat.tools.terminal.autoApprove": {
        "/^npm (test|run lint)$/": true,
        "/^git (status|diff|log)\\b/": true,
        "/^git push\\b/": false,
        "rm": false
    }
}

Copilot CLI does the same thing with --allow-tool and --deny-tool, and most other agents have an equivalent. Whichever you use, keep these rules in your user settings rather than a settings file inside the repo. If the agent can edit the file your approval rules live in, it can change those rules (and in 2025, a Copilot vulnerability let a prompt injection do that).

What it doesn't protect you from

Approvals decide which commands run, but once a command is approved, it runs with your full access. And some harmless-looking commands run code you never see.

Approving npm install, for example, runs the install scripts of every package in the tree. That's how the npm attack above got onto people's machines.

Use this when you're working in your own trusted project and watching what the agent does. On its own, it's the bare minimum.

Approach 2: A built-in sandbox

A sandbox limits what the agent's commands can touch, so even if it gets tricked into running something nasty, it can only reach the project folder. Of everything in this guide, this is the change I'd make first.

How it works

These sandboxes lean on isolation your operating system already has, like Seatbelt on macOS and bubblewrap on Linux. That's what Microsoft's Execution Containers wrap up for Copilot.

The rules are enforced by your operating system rather than the agent, so the agent can't give itself more access.

Setting it up

In Copilot CLI, it's one command inside a session:

Text
/sandbox enable

In VS Code, add this to your user settings:

JSON
{
    "chat.agent.sandbox.enabled": "on"
}

Once it's on, the agent can write to your working directory and temp folders, and everything else (including the rest of your home directory) is blocked. Other agents have the same idea under different names (Claude Code has /sandbox, and Codex has its sandbox modes), so check what yours offers and switch it on.

Add a network allowlist

Depending on your tool, the sandbox may still allow outbound internet access by default (Copilot's and VS Code's both do). That means your files are protected, but anything the agent can read could still be sent somewhere.

The fix is to list the hosts your project actually needs, so everything else gets blocked:

JSON
{
    "chat.agent.sandbox.enabled": "on",
    "chat.agent.sandbox.network.allowedDomains": [
        "github.com",
        "api.github.com",
        "registry.npmjs.org"
    ]
}

Start small. You'll probably need GitHub and your package registry (npm, Packagist, PyPI) and not a lot else. If something breaks, you'll see which host was blocked and can add it.

What it doesn't protect you from

When a command fails inside the sandbox, some tools will ask whether to run it outside instead. If you approve that, it runs with your full access, which undoes all of the above. Say no unless you know exactly why it needs out, and add the folder or host it needs to your sandbox settings instead.

It's also worth knowing that the sandbox mainly covers the commands the agent runs. Some tools, like remote MCP servers, sit outside it, so only connect the ones you trust.

Use this when you're doing everyday work on your own machine. Paired with the approval groups from Approach 1, this should be your default.

Approach 3: A dev container

If you haven't used one before, a dev container is a Docker container set up specifically for working on a project. You describe it in a devcontainer.json file that lives in your repo (which base image, which tools to install), and your editor builds the container and connects to it.

From then on, your editor still looks and feels the same, but the terminal, your build tools and your agent all run inside the container. Your project folder is mounted in, so edits still show up locally, but the rest of your machine isn't there at all.

What you'll need

  • Docker installed and running (Docker Desktop is the easiest option, but a Docker-compatible alternative like OrbStack works too).
  • An editor that supports dev containers. In VS Code, that's the Dev Containers extension. GitHub Codespaces, JetBrains IDEs and Cursor support them too.

Setting it up

Add a .devcontainer/devcontainer.json file to your project. Here's a minimal one for a Node project:

JSON
{
    "image": "mcr.microsoft.com/devcontainers/base:ubuntu",
    "features": {
        "ghcr.io/devcontainers/features/node:1": {}
    }
}

This starts from Microsoft's base Ubuntu image and adds Node on top using a "feature", which is just a ready-made install script for a tool. Swap these out for whatever your project needs (there are features for PHP, Python, Go and loads more).

Then run Dev Containers: Reopen in Container from the VS Code command palette. The first build takes a minute or two, but after that it opens quickly. Everything you (and your agent) run in the terminal now happens inside the container.

If you're using VS Code's Agents window, there's now a Use Dev Container option that runs the agent session in your project's dev container. Most agents (Copilot, Claude Code, Codex) can also just be installed inside the container and run from its terminal.

What it doesn't protect you from

A container isn't automatically locked down, so there are a few things to watch.

First, the network is wide open, because Docker containers can reach the internet by default. If you want an allowlist, you'll need a firewall inside the container. Claude Code's reference dev container includes an init-firewall.sh script that's a good starting point to borrow, even if you use a different agent.

Your Git access also comes with you. VS Code automatically forwards your SSH agent and copies your .gitconfig into the container, so the agent can push anywhere you can. Keep git push on your "never" list.

And whatever you mount is visible to the agent, so don't mount your home directory, ~/.ssh or cloud credential files into the container, or you've undone the point of using one.

Use this when you want to leave an agent running on its own for a while, you want to turn off approval prompts, or you want everyone on your team working in the same environment.

Approach 4: A separate machine

The most locked-down option is to not run the agent on your machine at all. Cloud agents like Copilot's cloud agent, Codex in the cloud and Claude Code on the web pick up a task, work in a temporary environment, and hand you back a pull request.

How it works

There's nothing of yours on that machine except the repo you've given it. Copilot's cloud agent is a good example of how these are locked down:

  • It can only push to its own copilot/ branch.
  • GitHub Actions workflows don't run on its pull requests until someone with write access approves them.
  • The person who asked for the pull request can't approve it.
  • Internet access is restricted by a firewall.

What it doesn't protect you from

The agent still has access to your repo and to any secrets you add to its environment. So the same rule applies here as everywhere else, and you should only give it the secrets it needs to run your tests.

It's also slower to work with. You hand over a task and review what comes back, which is great for some jobs and frustrating for others.

Use this when you've got a well-defined task you'd happily write up as an issue for a colleague, like a bug fix, a small feature or a round of dependency updates. It's also the safest place to point an agent at code you don't trust.

Which approach should you use?

You don't have to pick just one. Here's what I'd recommend depending on what you're doing.

Working alongside an agent in your own project

Use the built-in sandbox with a network allowlist, and sort your commands into the three approval groups. This covers most day-to-day work.

Leaving it to run on its own

If you're kicking off a long task and walking away, you can't approve anything anyway. Use a dev container with a firewall (or a cloud agent), make sure there are no real credentials in it, and review the diff when you get back.

Trying out code you don't trust

Cloning a random repo or testing a package you've never heard of? Don't point an agent at it on your main machine. Use a cloud agent, or a container or VM with nothing of yours mounted into it.

Handing off a well-defined task

Write it up as an issue and give it to a cloud agent. You'll get a pull request to review, and nothing ever runs on your machine.

So, how much access?

As little as it needs to finish the task without asking you every ten seconds. For most of us, that's write access to the project folder, a short list of hosts, no production credentials, and approval prompts for the handful of commands you'd regret.

Most of this only takes a few settings now. I'd start with your credentials and the sandbox, then reach for a container or a cloud agent when a job needs more.