DEV Community

Lucas
Lucas

Posted on

Why I Don’t Want AI Coding Agents to Have Shell Access by Default

AI coding agents are becoming very good at working with real codebases.

They can inspect a repository, trace bugs across multiple files, suggest architectural changes, write tests, and increasingly implement entire features.

But there is a security question I think we are moving past too quickly:

How much access does an AI actually need to do useful work?

When I want an AI model to review my code, I usually want it to do things like:

understand the project structure;
read source files;
search for symbols or patterns;
trace how components interact;
identify bugs;
review a proposed implementation.

None of those tasks inherently require unrestricted shell access.

Yet many agent workflows bundle code access together with capabilities such as:

executing shell commands;
running Git;
launching processes;
reading arbitrary filesystem locations;
modifying arbitrary files.

That makes the agent much more capable.

It also dramatically increases the blast radius when something goes wrong.

Capability and access are different things

A stronger model does not necessarily need stronger permissions.

Suppose I ask an AI:

Review the authentication implementation and tell me if you see any security issues.

For that task, the model needs information.

It needs to read the relevant repository.

It probably does not need permission to:

run arbitrary commands
read my entire home directory
inspect unrelated projects
modify source files
access credentials
delete files

This seems obvious when written out.

But developer tooling often treats repository access and machine access as almost the same thing.

I wanted to separate them.

The principle: least privilege

Traditional security engineering has a simple idea:

Give a system only the permissions it needs to perform its job.

AI agents should not be an exception.

If I am using one model as a reviewer, its permissions should reflect the role of a reviewer.

That might mean:

✓ list repository files
✓ read approved files
✓ search the repository

✗ execute shell commands
✗ run Git
✗ launch processes
✗ read outside the repository
✗ arbitrarily modify source code

This doesn't eliminate every risk.

But it turns the question from:

"Do I trust this AI with my computer?"

into something much narrower:

"Do I trust this AI to inspect this repository through these specific operations?"

That is a much easier security boundary to reason about.

This is why I built RepoRelay

I recently built an open-source project called RepoRelay around this idea.

RepoRelay is an MCP server that sits between an AI client and a local repository.

The architecture is roughly:

AI / ChatGPT

Secure MCP connection

RepoRelay

one explicitly approved repository

Instead of exposing a general-purpose shell or filesystem API, RepoRelay exposes a deliberately small set of repository operations.

The read-only surface is essentially:

open_workspace
list_files
read_file
search_files

The important part isn't the number of tools.

It's what isn't there.

There is no shell tool.

There is no Git tool.

There is no process-execution tool.

There is no generic "write this file anywhere" tool.

The approved repository becomes the boundary.

"One repository" sounds simple. It isn't.

A security boundary based on filesystem paths has plenty of edge cases.

Checking that a requested path starts with:

C:\Projects\my-app

is nowhere near sufficient.

A tool like this has to think about things such as:

.. traversal;
absolute paths;
path canonicalization;
symbolic links;
junctions and reparse points;
hard links;
sensitive files;
hidden credential locations;
bounded reads and searches.

For example, a request for:

../../some-other-project/.env

should obviously fail.

But the less-obvious escape mechanisms matter just as much.

RepoRelay therefore treats containment as an enforced security property rather than a prompt instruction.

The AI isn't being told:

"Please stay inside this folder."

The server is supposed to make leaving the folder impossible through the tools it exposes.

That distinction is important.

Sensitive files deserve another boundary

Even inside an approved repository, there are files I usually don't want an AI reviewer reading.

The most obvious example is:

.env

A repository may also contain credentials, private keys, or other sensitive material.

So "the AI may read this repository" should not automatically mean:

"The AI may read every byte under this directory."

RepoRelay blocks classes of sensitive paths separately from the repository-root boundary.

That gives you two layers:

Is this inside the approved repository?

yes

Is this file allowed to be exposed?

yes

read

Again, none of this is revolutionary security theory.

It's applying established ideas to AI tooling.

Reviewer and implementer should not always be the same agent

This led me to another design decision.

I often use one AI system to implement code and a stronger model to review the result.

Those are different roles.

The implementer may genuinely need local execution capabilities:

edit code
run tests
compile
use Git

The reviewer often doesn't.

So instead of giving both agents identical privileges, I prefer a workflow like:

Local coding agent

implements change

repository / commit

RepoRelay

strong reviewer model

review

This also creates a useful separation of concerns.

The model that wrote the code isn't necessarily the model that decides the code is good.

But what if the reviewer needs to request changes?

Pure read-only access is the cleanest security model, and RepoRelay supports it.

But I also wanted to experiment with a constrained reviewer → implementer workflow.

Instead of allowing arbitrary writes, RepoRelay can expose a few predetermined handoff files.

Conceptually:

ChatGPT

NEXT_TASK.md

local coding agent

implements changes

RESULT.md

ChatGPT

REVIEW.md

The reviewer can communicate what should happen next without gaining generic write access to the source tree.

That's a very different permission from:

"Edit whatever file you want."

The goal is not zero capability.

The goal is bounded capability.

Why not just use operating-system permissions?

OS-level isolation is valuable, and a tool like RepoRelay is not a replacement for containers, VMs, sandboxing, or proper system permissions.

Those solve a broader problem.

RepoRelay is trying to solve a narrower one at the application layer:

What operations should this particular AI client be able to invoke?

Those layers can complement each other.

You might eventually have:

OS / container sandbox
+
MCP-level capability restrictions
+
repository containment
+
sensitive-file filtering

Security tends to work better when it does not depend on a single control.

What RepoRelay does not claim

I think security-oriented projects should be explicit about their limitations.

RepoRelay is not an operating-system sandbox.

If malicious software is already running under your user account, an MCP server cannot magically secure the rest of the machine from that software.

It also doesn't make AI-generated code safe.

A reviewer can still miss vulnerabilities.

The purpose is narrower:

Reduce the authority granted to the AI connection itself.

That still matters.

If the task requires reading four source files, giving the model the ability to execute arbitrary commands is unnecessary additional authority.

AI tooling needs better permission design

As models improve, I think permission design is going to matter more, not less.

A weak model with powerful permissions is dangerous because it can make mistakes.

A very capable model with powerful permissions deserves careful thought for a different reason: it can do much more.

The answer can't simply be:

"The model is smarter now, so give it everything."

We should be asking:

What is the smallest useful interface for this task?

For code review, that interface can be surprisingly small.

And once the permissions are explicit, they become much easier to inspect, test, audit, and reason about.

RepoRelay is open source

RepoRelay is still a very new project, and I'm actively working on the security model and developer experience.

It's MIT licensed and available on GitHub:

github.com/Lukie-81/RepoRelay

You can install it through npm:

npm install -g reporelay-mcp@latest

I'm especially interested in feedback from people working on MCP, agent security, local-first tooling, and coding-agent workflows.

I'm sure there are threat-model assumptions and edge cases I haven't considered yet.

That's also part of why I wanted to make it open source.

The broader question is bigger than RepoRelay:

When an AI only needs access to your code, why should we automatically give it access to your machine?

Top comments (2)

Collapse
 
peterbuildssecure profile image
Peter

The reviewer/implementer capability split is a useful boundary. One implementation detail I'd test aggressively is the gap between validating a path and actually opening it.

Canonicalizing a path, confirming it is inside the repository, and then opening it by pathname still leaves a TOCTOU window: a symlink, junction, or reparse point can change between the check and the read. Where the OS supports it, containment is stronger when reads are resolved relative to an already-open repository directory handle, with beneath-root and no-reparse/no-symlink semantics enforced during the open itself.

I'd keep permanent negative fixtures for:

  • a symlink changed after validation;
  • a nested junction escaping the root;
  • a hard-link alias to a blocked file;
  • case and Unicode normalization collisions;
  • a sensitive file renamed to an allowed-looking path;
  • a large or cyclic tree intended to exhaust search limits.

Read-only also limits machine impact, but repository text is still untrusted input to the reviewer. Any NEXT_TASK.md handoff should be treated as a proposal, not authority for the implementer to execute commands or widen scope.

Collapse
 
lukie81 profile image
Lucas

This is exactly the kind of scrutiny I was hoping to get by releasing it open source. Thank you.

The TOCTOU distinction is a really good point. Validating a canonical path and then opening that pathname is not equivalent to enforcing containment as part of the open itself. I’m going to audit RepoRelay specifically for that gap and turn the cases you listed into permanent negative/regression tests.

I also agree on the handoff boundary. NEXT_TASK.md should be treated as untrusted reviewer output, a proposal for the implementer to evaluate, never authority to execute commands, expand permissions, or widen scope.

The broader goal with RepoRelay is defense in depth rather than treating “read-only” as synonymous with “safe.” This gives me several concrete cases to harden against. Appreciate the detailed review.