/blog/

2026 0419 Protecting .git from malicious agents

I realized you can use containers to run Claude Code in yolo mode with Internet access relatively safely, without needing to maintain a dedicated VM.

This might sound obvious. The whole point of containers is to isolate the contained processes from the host. Run Claude in a container, mount your project inside the container, and call it a day. This works fine, and will certainly prevent Claude from running commands on the host or accessing files outside your project directory.

But when you’re working on a software project, Claude is still writing the code you’re going to run on the host, and because it has control of your .git directory, you can’t even inspect it safely.

Why not? Because .git/config includes configuration for viewers like external diffing tools, which means arbitrary code execution during git diff. If you give Claude write access to .git/, then run git diff on the host, you give it the ability to lie to you about the contents of the diff, or just run code on your host directly. (And you can’t trust git diff in the container at all, since Claude controls shell configuration and lots of other things in that context.) This is also true for git show which will use the same diff drivers, git checkout/git pull/etc which uses smudge filters, git add which uses git clean filters, and probably lots more.

The fix is simple: after mounting the project’s directory inside the container read/write (perhaps to /src), mount the project’s .git directory read only on top (e.g. to /src/.git). The agent can still see repository history and make changes to code, and you are able to safely review them before you commit.

This method does have a big weakness, though: it can only protect you from git commands you run in the repository root. If a malicious agent creates a new git repo (or submodule) in a subdirectory of your project and you run commands there, they are run in the context of that repo, which the agent controls. git status is safe in any subdirectory, but even git status -v isn’t, as it shows diffs via diff drivers.

A few considerations:

  1. If you have git hooks that run scripts in your own git repo, you should disable them, as Claude controls their contents and git on the host will run them automatically.

  2. There are .gitattributes files that can exist in any directory, but they can only point to diff/merge/filter names already specified in your git configuration, so I believe they are safe to allow the agent to modify if you trust that.

  3. This is not as convenient for cross-repo work, where you might actually prefer a whole-VM approach.

And some other thoughts:

  1. I first tried to use AppArmor inside the container to prevent writes to any file or directory called .git, .gitattributes, or .gitmodules, in any directory. This is a more generic solution and it solves the problem of running git commands in a subdirectory, except that it depends on kernel AppArmor support. Docker Desktop doesn’t ship with AppArmor support in its VM’s kernel (why would it?), so it is actually only a useful design on Linux systems where you also control the kernel configuration.

  2. I end up needing custom images per-project to install things like prerequisites and tools, so I don’t have a single container image that does this for all my projects. It’s project-specific, like a Makefile.

  3. If I tightly control agent input on disk and prohibit Internet access, I don’t bother with this.

Stay safe out there.

Responses

Webmentions

Hosted on remote sites, and collected here via Webmention.io (thanks!).

Comments

Comments are hosted on this site and powered by Remark42 (thanks!).