I came across a security bug recently that I haven't been able to stop thinking about, mostly because the bug itself is almost boring. There was no clever prompt injection, no model escaping a sandbox, and nobody convincing an AI to ignore its instructions through some weird encoded message. The model didn't even need to be contacted. You could open a project folder, your coding tool would run Git to understand the repository, Git would read some configuration, and suddenly someone else's code could be running on your machine.
The vulnerability class is called GitSpawn. Researchers at Manifold Security found eight related issues across seven coding agents, including Claude Code, Codex, Cursor, Goose, Hermes Agent, Qwen Code and Grok Build. One of the main paths involved core.fsmonitor, a legitimate Git configuration option that can point to an external program. Coding agents routinely run commands such as git status or git diff in the background to understand a repository, and those operations can cause Git to invoke the configured helper. In vulnerable versions of these tools, that could happen outside the agent's sandbox and without the approval prompt you'd normally expect before something executes on your machine.
I think the interesting part isn't really that an AI coding tool had a security vulnerability. Software has vulnerabilities all the time. What interests me is that somewhere along the way we've made opening a folder surprisingly close to executing a program.
Repositories aren't really just folders anymore
I think most of us still have an old mental model of a repository. It's a directory containing source files. You can open it, look around, search for something, maybe change a few files, and nothing should actually happen until you deliberately run the software. That model hasn't really been true for a while.
Open a modern project and quite a lot can happen automatically. Your editor starts extensions and language servers, Git commands run in the background, files get indexed, formatters discover configuration, development environments get detected and various tools begin trying to understand what kind of project they've been dropped into. Most of this is incredibly useful. I definitely don't want to manually explain my repository to every tool I use.
The problem is that repositories increasingly contain instructions for the tools inspecting them. A project can have editor settings, tasks, formatter configuration, package scripts, development containers, compiler plugins, CI configuration and plenty of other things that aren't really source code in the traditional sense. Some of those eventually point to executable programs.
VS Code has had Workspace Trust for years for basically this reason. Its Restricted Mode limits things like tasks, debugging, workspace settings, extensions and terminals when you open unfamiliar code. The interesting thing about that feature is what its existence implies: simply browsing a repository is no longer obviously a passive operation.
We've slowly turned a repository from a collection of files into a description of an entire development environment. That's incredibly convenient, but it also means the security boundary has changed without our mental model necessarily changing with it.
Convenience keeps eating the boundary
Most automatic developer tooling exists for completely reasonable reasons. When I open a project, I want my editor to immediately know what language it uses. I want Git state available without asking for it. I want my formatter configured correctly, my imports understood and my coding agent to know which files I've modified before I even start explaining the problem.
Having to manually configure all of this every time would be ridiculous, so tools automatically inspect more things. Then they inspect a little more. Eventually "understand this repository" means running a collection of commands, loading configuration and starting processes, some of which are influenced by the repository being inspected.
That's where things get weird because we normally think about security in terms of explicit execution. Don't run random shell scripts. Don't install binaries you don't trust. Don't paste a command from a random website into your terminal without understanding it. Those rules are easy enough to understand because there is a visible moment where you decide to execute something.
There is another category that's much harder to reason about: software executing something while apparently trying to inspect something else. git status feels like a read operation. In the GitSpawn case, however, repository-controlled configuration could cause that seemingly harmless operation to invoke another program. The command itself wasn't really the problem. The trust relationship around the command was.
AI made an old problem much easier to see
GitSpawn naturally gets described as an AI security problem because coding agents exposed the vulnerability, but I think that's slightly misleading. The model wasn't really doing anything interesting here. The vulnerability existed in the plumbing underneath it. In several cases, the dangerous command could execute while the agent was gathering context, before the normal model-driven tool flow had even started.
What AI changes is how autonomous developer tools are becoming. Instead of waiting for me to click something, the software looks around on my behalf. It reads files, runs commands, checks Git state, launches subprocesses and builds a mental picture of the project before I have even decided exactly what I want it to do. That's what makes these old assumptions more dangerous.
A behaviour that was reasonably safe when a human deliberately invoked it might not be safe when an agent automatically invokes it against arbitrary input. A configuration option that's perfectly useful when I created it myself becomes very different when it arrived inside a folder somebody sent me.
None of the individual pieces necessarily changed. The way we're composing them did. I suspect we'll keep finding bugs like this because we're taking developer tools designed around a human being in the loop and putting them underneath systems designed specifically to remove the human from more and more of that loop.
"Read-only" probably needs a better definition
I've started thinking that developer tools need a stricter idea of what inspecting a project actually means. If I'm opening an unknown repository because I want to understand what's inside it, the safest version of that operation should be extremely boring. Read files, parse text, inspect metadata and maybe build an AST. None of that should require trusting the project.
The moment inspection starts executing repository-defined hooks, invoking arbitrary binaries, evaluating executable configuration, loading plugins or starting shells, I don't think we're really inspecting anymore. We're executing things as a side effect of inspection.
This gets difficult because modern developer tooling is basically built out of composition. Git calls hooks. Editors call formatters. Formatters read configuration. Language servers invoke compilers. Compilers load plugins. Package managers run lifecycle scripts. Shells load environment configuration. Every one of those behaviours can be completely reasonable on its own, and then two tools get connected in a way where one assumes the other's normal behaviour is safe.
Security boundaries often disappear in those gaps.
Maybe the better mental model for a repository is something closer to a document containing macros. A document looks like data until the document itself starts containing instructions for the software opening it. At that point, "open this" and "trust this" need to become separate operations.
Source repositories increasingly look like that. They aren't just source code anymore. They can describe editor behaviour, build environments, containers, package scripts, CI pipelines and instructions for autonomous tools. They're partially data and partially executable environment. Treating an unfamiliar repository as inherently safe because "I haven't run the code yet" doesn't make much sense anymore.
Sandboxing needs to start before the agent does
One of the things I found most interesting about GitSpawn is that some of the affected tools already had permission systems or sandboxing. The problem was that the dangerous behaviour could happen while the application itself was preparing the session. If repository-controlled code executes before the sandbox or approval boundary becomes relevant, having a really good sandbox afterward doesn't help much.
That's probably the architectural lesson here. Security can't begin when the model decides to call a tool. It has to begin when untrusted input enters the system.
If an application opens an unfamiliar repository, everything automatic after that point probably needs to assume the repository is hostile until the user decides otherwise. That might mean sanitized Git operations, disabled hooks, restricted configuration and a genuinely passive inspection mode. It's less convenient internally, but the security model becomes much easier to understand.
I still want all of this tooling to be automatic. I don't want to manually run git status, start my language server, configure my formatter and explain the repository structure every time I open a project. Automatic context is fantastic, and coding agents would be dramatically worse without it.
I just think we're reaching the point where the convenience has become powerful enough that the security model needs to catch up. The safest software used to be software that didn't execute random programs. Now we're deliberately building tools whose entire purpose is to execute programs for us, which is fine, but there should still be a meaningful distinction between looking at something and trusting it.
A folder should be allowed to tell my tools what it contains. I'm less convinced it should be allowed to tell them what to run.
Top comments (0)