Агентам выкатили патч. А git status в чужой папке до сих пор выполняет чужой код
Первого сентября Manifold Security выкатили GitSpawn: восемь находок в семи кодинг-агентах. Суть в одной фразе. Тебе присылают папку, ты открываешь её агентом, и на твоей машине выполняется чужой код. Ты ничего не запускал и не набрал ни одной команды.
Механика такая. В git есть настройка core.fsmonitor, её значение это команда, которую git запускает сам, чтобы узнать, какие файлы изменились. Лежит она в .git/config самого репозитория, и git выполняет её при любом обновлении индекса. То есть на git status и на git diff. На том, что агент делает в фоне сразу после открытия папки, чтобы собрать контекст. До твоего первого промпта, а в худшем случае до диалога о доверии к папке.
Я собрал репозиторий-ловушку и прогнал:
$ git config core.fsmonitor "$PWD/.git/p.sh" # так это лежит в .git/config
$ git status --short
A README.md
$ cat ../out/marker.txt
PAYLOAD RAN 2026-09-16T09:41:12Z
Один git status, и скрипт отработал.
Хорошая новость, которая ничего не меняет
Вендоры отреагировали. Claude Code закрыл путь через core.fsmonitor в версии 2.1.196. Я проверил на 2.1.271: запустил свежий Claude Code в той же самой папке-ловушке, и payload не выполнился. Codex, Cursor и Goose тоже пропатчены.
А теперь посмотри на две команды выше ещё раз. Это не агент. Это я руками набрал git status в той же папке, и код выполнился.
Патч агента защищает ровно одно: фоновые вызовы git, которые делает сам агент. Он не делает чужую папку безопасной. В ней по-прежнему лежит конфиг, который выполняет команду, и его триггерит что угодно, дошедшее до git: твой собственный git status, скрипт сборки, make, плагин редактора, CI-раннер, любая утилита, которая шелится в git, чтобы узнать текущую ветку. Ты открыл присланный zip, зашёл посмотреть, что внутри, и всё.
Плюс три вещи, из-за которых опираться на патч вендора рано:
Чинили точечно. Агенты не запретили выполнять чужой конфиг, они вычищают опасные ключи в тех местах, откуда зовут git. Такое ломается при добавлении новой фичи с новым вызовом. Manifold сообщили Anthropic о втором пути в Claude Code, уже не через core.fsmonitor, и на момент их публикации, на версии 2.1.252, он закрыт не был.
Запатчены не все. На первое сентября Qwen Code, Grok Build и Hermes Agent оставались уязвимыми.
Есть отдельный вектор с собственной CVE. Вложенный bare-репозиторий: git не даёт выложить путь с именем .git, но bare-репозиторию хватает трёх обычных каталогов, HEAD, objects и refs, а они спокойно коммитятся внутрь нормального репозитория. Git находит их при обходе дерева и применяет их конфиг. Это CVE-2026-45033 в GitHub Copilot CLI, чинили в 1.0.43.
И отдельно неприятное: класс дыры старый. VS Code закрыл его ещё в 2021 году, введя доверие к рабочей области. Пришли агенты, и урок забыли.
«Я же не клоню что попало» тут не работает
Клонирование ни при чём. Склонировать враждебный URL безопасно: git clone, fetch и pull payload не запускают. Стреляет папка, которая приехала к тебе уже файлами, с .git внутри. Прислали .zip, кинули на общий диск, синхронизировали, дали флешку. Разархивировал, зашёл посмотреть, попал.
Что с этим делать
Раз стреляет папка, а не агент, и раз триггернуть может любая утилита, проверять надо саму папку, до того как ты в неё зашёл. Я сделал команду ровно для этого:
$ stroq inspect ./that-repo-someone-sent-me
BEFORE YOU APPROVE ANYTHING (1)
.git/config — core.fsmonitor: this repository sets a git configuration key
whose value git runs as a command, which happens during an ordinary index
refresh — an agent typing `git status` triggers it, before any approval
fix: git config --get core.fsmonitor — and remove it if you did not set it
When you open or build it (1, ordinary — not findings)
package.json — postinstall
Она читает .git/config на ключи, значение которых git исполняет, находит вложенные bare-репозитории, смотрит .gitattributes, .husky, .devcontainer и postinstall-скрипты. Всё, чем репозиторий может выстрелить при открытии. Код возврата 1, так что команда встаёт в pre-commit и в CI.
А если надо не проверить, а прямо сейчас работать в чужой папке и не отхватить:
$ stroq inspect --env ./that-repo
export GIT_CONFIG_COUNT=2
export GIT_CONFIG_KEY_0=core.fsmonitor
export GIT_CONFIG_VALUE_0=false
export GIT_CONFIG_KEY_1=safe.bareRepository
export GIT_CONFIG_VALUE_1=explicit
Это тот же механизм, которым GitHub чинил свою CVE, только на стороне пользователя. core.fsmonitor глушится, автообнаружение bare-репозиториев выключается, и глушится это на уровне команды, то есть выше конфига репозитория. С этими экспортами моя ловушка молчит: git status отрабатывает, маркер пустой. Проверял на git 2.53.0.
Одна честная деталь. Такая проверка работает, только если ты её запустил, а обёртка, только если ты стартуешь через неё. Это не забор, который стоит сам, это фонарик, который наводят на папку до того, как в неё зашли. Против штуки, которая срабатывает раньше любой защиты внутри сессии, единственный рабочий момент это «раньше».
Зачем мне это
Я пишу Stroq, потому что сам пускаю агентов в свои репозитории и хочу знать, откуда прилетела команда, прежде чем она выполнится. GitSpawn довёл эту мысль до конца: иногда команды ещё нет, есть только папка, и зайти в неё уже значит выполнить чужой код.
Открытое, Apache-2.0, ставится одной командой. Через curl | sh ставить не предлагаю, это ровно тот паттерн, против которого всё и затевалось.
npx @stroq/cli inspect ./repo # проверить папку до того, как ты в неё зашёл
Код: github.com/AGGIB/Stroq. Найдёшь у себя core.fsmonitor, который ты не ставил, напиши, откуда приехала папка. Это те данные, которых мне сейчас не хватает больше всего.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.