What Did the Agent Just Push? Auditing Git for AI Agents

speckx2 pts0 comments

What Did the Agent Just Push? Auditing Git for AI Agents – Eugene Petrenko

You hand a repository to an autonomous AI Agent and let it work. It clones, branches, commits, pushes,<br>maybe opens a pull request. A few minutes later it tells you it is done. Two questions stay on the table,<br>and neither has a comfortable answer:

Which commits did it actually produce? Not the summary it wrote for you — the real objects that<br>landed on the server.

Are you sure it only touched the branches you allowed? One confused agent force-pushing main is<br>a bad afternoon.

I have been running fleets of agents on the same codebases for a while now (see<br>Orchestrating AI Fleets and the<br>Git Fork Pattern), and the more agents you run, the<br>more these two questions turn from curiosity into operational risk. This post is about answering them at<br>the layer where the truth lives: git itself .

This post is the approach: why this is a git problem, the one rule that makes everything else possible, and<br>the two mechanisms — a git proxy and git hooks — at a level you can reason about and act on. The deepest<br>wire-protocol mechanics of the proxy are involved enough that they get their own follow-up; here we cover<br>the shape and the decisions, with enough pseudo-code that your AI Agent can start implementing it in your<br>stack.

Why This Is a Git Problem, Not a Policy Document

The naive answer is “just tell the agent which branches it may touch.” That is a policy. Policies are<br>suggestions to a process that has a shell, a network, and a strong urge to finish its task. Agents are<br>smart — give one a constraint phrased as a request and it may find a creative way around it, not out of<br>bad intent but because working around obstacles is literally what we trained it to do.

So we do not rely on asking nicely. We rely on two properties:

Blast radius — only the heads we selected can change on the real server, enforced somewhere the<br>agent cannot route around.

Provenance — every commit the agent created is captured and attributed, so we can recover, review,<br>and audit it after the fact. This will be a great source for iterative learning later.

There are two ways to get there. The first is a git proxy that sits outside the agent’s sandbox — the<br>hard boundary. The second is git hooks baked into the sandbox image — a lighter, best-effort layer for<br>when you own the image but not the network path. We use the proxy as the real wall and treat hooks as<br>extra telemetry. Here is why.

The One Rule Underneath Everything: Don’t Give Agents the Real Keys

Before any proxy or hook, there is a decision that makes the rest possible.

The agent never holds the credentials to the real git server.

Inside the sandbox, the agent gets a short-lived, scoped token that authenticates it to our endpoint —<br>not to GitHub or Space, not to your internal git host. We inject that token the boring way: a git credential helper<br>or a URL rewrite, never the real key on disk. The real push credential lives in the proxy, which the agent<br>cannot read. When a push is allowed, the proxy authenticates upstream with its own service credential.

This is the property that survives a clever agent. A sandbox is a permission boundary, and inside its own<br>sandbox an agent may have enough rights to do almost anything — read its environment, rewrite files,<br>disable the tooling we installed. If the real key were anywhere in that environment, a determined agent<br>could find it and talk to the Git server directly, and every control we built would be decoration. Because the<br>key is not there, the worst an escaped agent can reach is the proxy — and the proxy enforces policy and<br>holds the key. The blast radius is bounded by where the credential lives, not by how well-behaved the<br>agent is

I want to note – the pattern how we are going to limit the agent push/pull operations is not standard,<br>and potentially is hard-to-impossible to implement out of the box with GitHub, Space or any third-party Git host.<br>Agentic AI opens yet another direction for us – software is now very cheap to build, given you know how.

Below we explain enough ideas to implement it. Git supports multiple protocols, including HTTP, SSH, and Git over TCP.<br>We decided to use HTTP below, but the same technique can be applied to other protocols as well, mainly to SSH.

Solution 1: The Git Proxy — the Hard Boundary

A git push over HTTP is a surprisingly inspectable conversation. If you put a proxy on the path between the<br>agent and the server, you can read the whole exchange, decide whether to allow it, and capture everything<br>that flows through — without the agent being able to tell the difference, and without it being able to go<br>around you, because it has nowhere else to go

What a push actually looks like on the wire

Git’s “smart HTTP” protocol does a push in two HTTP requests<br>(gitprotocol-http):

Ref advertisement — GET /info/refs?service=git-receive-pack. After a # service=git-receive-pack<br>header line and a flush, the server lists every ref and its...

agent proxy push real agents server

Related Articles