Перейти к содержимому

Кейс: GitSpawn — как Git-вызовы позволяют выполнить код в Claude Code, Codex и Cursor

Первого сентября 2026 года Manifold Security опубликовала исследование GitSpawn — и оно не про модель, не про промпт-инъекции и не про «умный» обход классификатора. Восемь находок в семи кодинг-агентах, четыре из них оставались незакрытыми на момент публикации. Каждая заканчивается выполнением произвольного кода на машине разработчика с его правами, без единого запроса подтверждения на экране — потому что агент запускает этот код сам, до того как вы успели сказать хоть слово.

Разбор по шагам ниже: как агенты собирают контекст о проекте, почему для этого используются git-команды, что в git-механике превращает обычный git status в исполнение чужого кода и как защититься. Здесь конкретная атака и её техническая цепочка; общая картина поверхности атаки кодинг-агентов собрана в гайде по безопасности ИИ-агентов. Версии агентов и статусы исправлений — на момент публикации, 08.09.2026.

Суть находки: репозиторий решает, что выполнит git-команда

Исследователи Manifold задались одним вопросом: что CLI-агент реально делает при запуске? Ответ одинаков для всех проверенных продуктов — агент собирает контекст о проекте, и заметная часть этого сбора выполняется через git.

Open a folder with Claude Code and it runs git status before you type anything. Before the workspace-trust prompt. On some agents, before you have even authenticated. If that folder came from somewhere else, the repository decides what that command runs.

Откройте папку с Claude Code — и он выполнит git status до того, как вы что-то введёте. До запроса о доверии к рабочей директории. На некоторых агентах — до того, как вы вообще авторизовались. Если папка пришла откуда-то ещё, содержимое репозитория решает, что выполнит эта команда.

— Francisco Rosales, Manifold Security, GitSpawn, 01.09.2026

Формулировка «репозиторий решает, что выполнит команда» — не метафора. Git, который агент вызывает для сбора контекста, читает настройки из .git/config самого репозитория. Часть этих настроек — параметры, которые указывают git-у, какую программу запустить. Репозиторий, полученный как папка с файлами — архив ZIP, синхронизируемая директория, флешка, — приносит такой конфиг с собой. Открыли папку агентом — и код из её конфига выполнился.

Пост Manifold Security «GitSpawn: A Single Flaw Lets Untrusted Repos Run Code»
Разбор GitSpawn на manifold.security (01.09.2026). Заголовок, автор и дата читаются; исследование позиционируется как класс уязвимостей, а не баг одного вендора.

Как агент выполняет git-команды до вашего участия

Контекст, который агент собирает на старте, зависит от продукта. Manifold приводит два примера из разных агентов:

git status --porcelain=2 --branch
git diff --name-only HEAD

Обе команды не выглядят подозрительно — такое вы писали бы сами. Но у них есть общее свойство: почти любая git-команда, которая трогает рабочее дерево, сначала обновляет индекс. А обновление индекса и есть «сток» — место, где git выполняет настроенные программы.

Классический пример — core.fsmonitor. Это настройка производительности для больших репозиториев: вместо того чтобы сканировать каждый файл на диске, git спрашивает внешний хелпер, что изменилось, и запускает его во время обновления индекса. Задокументированное штатное поведение. Настройка читается из .git/config самого репозитория, поэтому репозиторий может содержать:

[core]
    fsmonitor = <команда>

Дальше неважно, какую команду выбрал агент — git status, git diff, что угодно, обновляющее индекс. При обновлении индекса git запустит <команду> с правами пользователя, на хосте.

Способ доставки точен, и это важно: git никогда не переносит эту настройку сам. Клонирование враждебного URL ничего не делает, как и fetch или pull. Репозиторий должен прийти как файлы с уже лежащим внутри .git — то есть вектором становится всё, что перемещает директорию вместо клонирования: общий ZIP, расшаренная папка, синхронизируемый каталог, USB-флешка. Коллеги передают проекты друг другу именно так, консультанты отдают клиентам. Каждый proof-of-concept в исследовании был доставлен ZIP-архивом.

core.fsmonitor — не единственный параметр такого класса. Поэтому одна из находок ниже — вообще не про core.fsmonitor, а про другой git-параметр того же типа.

Почему запрос доверия и permission model не спасают

Логичный вопрос: а как же workspace-trust промпт, который Claude Code показывает при открытии чужой папки? Ответ в тайминге.

Сбор контекста происходит на старте сессии, до появления промпта о доверии к рабочей директории. На некоторых агентах — до авторизации. git-команда запускается как внутренний subprocess самого агента, вне песочницы, и permission model её вообще не видит — с точки зрения агента это его собственный код, собирающий контекст, а не пользовательское действие, которое надо подтверждать.

Когда выполняется git: сбор контекста на старте идёт до запроса доверия
Порядок событий: открытие папки → фоновый git для контекста (код из .git/config уже может выполниться) → запрос доверия → работа с моделью. Промпт доверия стоит после точки, где срабатывает уязвимость. Авторская схема по материалам Manifold Security.

Атака Rehberger на auto mode (26.08.2026) показала тот же паттерн с другой стороны: классификатор тоже оценивает отдельные действия, а не то, что произошло в подпроцессе до его решения. Разбор той цепочки — в кейсе о взломе auto mode. Общий вывод один: слой «модель + классификатор + промпт» ничего не решает, если исполнение случается в системном подпроцессе вне этого слоя.

Один и тот же паттерн, агент за агентом

Manifold нашла этот поток почти в каждом проверенном агенте — со своей точкой входа в каждом продукте:

Агент Когда срабатывает Когда сообщено Статус на 01.09.2026
Goose goose review собирает diff, payload выполняется до обращения к модели 13.07 (1.41.0) Исправлено в 1.44.0, CVE-2026-72718
Claude Code (core.fsmonitor) claude при открытии папки, до принятия trust-промпта 26.06 (2.1.193) Исправлено в 2.1.196
Claude Code (ultrareview) claude ultrareview до начала ревью, до trust-промпта 15.07 (2.1.210) Не исправлено, подтверждено на 2.1.252
Hermes Agent git status в директории сессии при первом сообщении 20.07 (0.18.2) Не исправлено, подтверждено на 0.21.0, CVE-2026-71963
Qwen Code git status на старте, до авторизации 07.07 (0.19.6) Не исправлено, подтверждено на 0.22.3
Grok Build git-вызов при первом нажатии клавиши, до отправки сообщения 14.07 (0.2.93) Не исправлено, подтверждено на 1.0.13
OpenAI Codex вариант того же класса 20.07 Исправлено (дубликат чужого репорта)
Cursor вариант того же класса 08.07 Исправлено (дубликат чужого репорта)

Таблица — по материалам первоисточника. Уточнение по Codex и Cursor — из апдейта Manifold от 01.09.2026:

Update, 1 September 2026. OpenAI’s Codex and Cursor were also affected. We tested and reported both; each came back as a duplicate of a report another researcher had already filed, and both have since been patched.

Обновление, 1 сентября 2026. Codex от OpenAI и Cursor также были затронуты. Мы протестировали и сообщили об обоих; каждый вернулся как дубликат репорта, который уже подал другой исследователь, и оба с тех пор исправлены.

— Manifold Security, GitSpawn

Находка по Hermes примечательна отдельно: CVE-2026-71963 присвоен независимым CNA — VulnCheck, а не вендором. Шесть попыток связаться по пяти каналам, приватный GHSA-адвайзори так и не был рассмотрен. Уязвимость подтверждена на актуальной версии 0.21.0 в день публикации исследования. Отчёт по Grok Build закрыли как дубликат репорта от 1 июля, который xAI до этого закрыла как информационный.

Цепочка GitSpawn по шагам

Если собрать механику в одну схему, получается короткая цепочка из четырёх звеньев — в ней нет ни одной ошибки рассуждений модели, только механика git и тайминг агента.

Цепочка GitSpawn: папка → git status → обновление индекса → код из конфига
Цепочка GitSpawn: untrusted-папка с .git внутри → агент на старте вызывает git для контекста → git обновляет индекс → срабатывает команда из .git/config (core.fsmonitor и аналоги) → выполнение кода с правами пользователя, без промпта и вне песочницы. Авторская схема по материалам Manifold Security.
  1. Папка. Разработчик получает проект как ZIP, общую папку или синхронизированную директорию — с уже присутствующим .git, включая .git/config, где прописан исполняемый параметр.
  2. Старт агента. Разработчик открывает папку агентом. Тот запускает git-команду для сбора контекста (ветка, изменённые файлы, статус) — до trust-промпта, а на некоторых агентах и до авторизации.
  3. Обновление индекса. git-команда обновляет индекс и на этом шаге запускает программу, названную в конфиге репозитория.
  4. Выполнение. Код выполняется как сам агент — от имени пользователя, на хосте, вне песочницы, без запроса подтверждения. Дальше у атакующего всё, что есть у разработчика: SSH-ключи, облачные credentials, токены из шелл-конфига, все репозитории на диске.

Manifold сознательно не публикует готовый репозиторий для атаки на коллег и не называет второй git-параметр из находки Claude Code, пока тот не закрыт. В тексте исследования это подчёркнуто отдельно.

Масштаб: почему это «не баг одного вендора»

Уязвимость не в модели и не в новом механизме. Она в обычной обвязке: subprocess, который агент запускает на старте, чтобы понять, где он находится. Поэтому класс широкий:

  • Claude Code — свыше 77 миллионов npm-загрузок в месяц (данные npm API за 28.07–27.08.2026);
  • суммарно по пяти проектам из разбора — около полумиллиона звёзд на GitHub: Hermes больше 237 000, Claude Code 143 000+, Goose 54 000+, Qwen Code 27 000+, Grok Build 26 000;
  • четыре из восьми находок оставались живыми на день публикации. Каждая была отправлена вендору приватно, повторно подтверждена на актуальном релизе перед публикацией и либо получила ответ, либо нет. Пять из восьми репортов вернулись дубликатами находок, которые другие исследователи подали независимо — один в тот же день.

Значит, класс ловят с разных сторон одновременно. Обсуждение вышло и на Hacker News — тред GitSpawn с ссылкой на исследование появился в день публикации.

Защита: что делать до открытия чужой папки

Рекомендация Manifold для разработчиков короткая:

If you receive a repository as files. Inspect .git/config before you open the directory with an agent. Any setting that names a program can run it.

Если вы получаете репозиторий файлами. Проверьте .git/config, прежде чем открывать директорию агентом. Любая настройка, которая называет программу, может её запустить.

— Manifold Security, GitSpawn

На практике — пять действий, от быстрых к надёжным.

1. Смотрите .git/config перед открытием. Один взгляд на конфиг занимает секунду:

cat <repo>/.git/config

Подозрительно всё, что называет программу для выполнения: core.fsmonitor, core.sshCommand, core.pager, core.hooksPath и аналоги. Если строка есть — репозиторий либо пришёл откуда-то ещё, либо уже вскрыт.

2. Проверяйте происхождение настроек. Выполните в директории репозитория:

git config --list --show-origin

Вы увидите, какая настройка откуда пришла — из системного, глобального конфига или из .git/config самого репозитория. Последний источник — тот, что контролирует отправитель папки.

3. Чужой репозиторий — клонируйте, а не распаковывайте. git clone не переносит локальный конфиг и хуки. ZIP, общую папку, синхронизацию и флешку для передачи своих проектов используйте осознанно: вместе с файлами передаётся .git с его исполняемыми параметрами.

4. Открывайте непроверенное в изоляции. Если репозиторий нужен для анализа, а не доверен — распакуйте в чистую директорию и запускайте агента в контейнере или VM, куда не смонтированы домашний каталог и ключи. Как собрать такую среду — в статье «Песочницы для ИИ-агентов» и в кейсе Micah Lee.

5. Обновляйте агентов и следите за changelog. Claude Code закрыл основной вектор к 2.1.196, Goose — в 1.44.0. Четыре находки на момент публикации не имели фикса — статусы меняются быстро, проверяйте актуальные версии.

Отдельно про git config safe.directory: эта настройка защищает от другого класса проблем (git отказывается работать в директории с чужим владельцем) и не закрывает исполняемые параметры конфига. Рассчитывать на неё против GitSpawn нельзя.

Чек-лист при работе с чужим кодом

  1. Репозиторий пришёл файлами (ZIP/папка/синхронизация) → сначала cat .git/config, потом открывать агентом.
  2. Любая настройка, называющая программу, в чужом конфиге → не открывать до очистки.
  3. Для ревью незнакомого кода — restricted-режим (Claude Code --restricted) или статический анализ без запуска.
  4. Для запуска агентов на непроверенном коде — контейнер/VM, без домашней директории, с отдельными credentials.
  5. Логирование команд агента и проверка diff перед слиянием.
  6. Автономные прогоны на чужих репозиториях — только в изоляции и под мониторингом.

Честные ограничения

  • GitSpawn — не промпт-инъекция. Цепочка вообще не касается рассуждений модели. Поэтому «более умная модель» этот класс не лечит — лечит только очистка конфига на стороне агента и изоляция.
  • Исправление не равно конец класса. Пять из восьми репортов — дубликаты чужих находок, найденных независимо. Это значит, что класс ищут многие, а вендоры иногда узнают о проблеме от третьих сторон.
  • Вторая находка Claude Code остаётся нераскрытой. Manifold намеренно не публикует git-параметр, пока он не закрыт. Публикация готового рецепта до фикса нанесла бы больше вреда.
  • Статусы устаревают за дни. Четыре неисправленных вектора на 01.09.2026 могли закрыться после публикации. Проверяйте актуальные версии агентов.
  • Проверка конфига — не панацея. Внимательный взгляд на .git/config ловит известные параметры. Неизвестный параметр того же класса вы не увидите — потому и нужен слой изоляции.
  • Контейнер сам по себе не спасает. Если в контейнер смонтирован домашний каталог с ключами, выгода от изоляции почти нулевая.

Российские реалии

GitSpawn не зависит от региона: атакуемый механизм — локальные git-вызовы агента, и он срабатывает одинаково, где бы вы ни находились. А вот агенты, которых это касается, имеют российскую специфику доступности.

Claude Code (Anthropic). Россия не входит в список поддерживаемых стран Anthropic: claude.ai, подписка и API не работают из российского IP без VPN, оплата картами РФ невозможна — реальные пути через иностранные/виртуальные карты, посредников и крипту. Но флаг --restricted и permission modes — локальные настройки CLI и от региона не зависят. Практика запуска Claude в dev-контейнерах описана в гайде на DTF.

Codex (OpenAI) и Cursor. Та же картина: из российских IP напрямую не работают, оплата — зарубежными картами через посредников.

Инструменты защиты — без ограничений. Docker, QEMU/KVM, песочницы ОС в России доступны. Подборка корпоративной песочницы от МТС — на Habr, серия про LLM-песочницы с Docker — на Habr, часть 2.

Русскоязычного разбора именно GitSpawn на момент публикации нет — тема закрылась за неделю до выхода этой статьи, и в рунете её ещё не разобрали. Общие материалы по безопасности агентов есть, ссылки выше. Если работаете с чужими репозиториями и агентами — правило то же, что и для всех: .git/config проверять до открытия, агента держать в изоляции.

Вывод

GitSpawn показателен тем, что атака не использует модель вообще. Кодинг-агент обязан собрать контекст о проекте до того, как вы что-то спросите, и делает это git-командами. Git по дизайну запускает программы из конфига репозитория. Репозиторий, пришедший файлами, приносит конфиг с собой. Соедините три факта — и получите выполнение кода до запроса доверия, вне песочницы и без единого подтверждения.

Для практики это означает: чужой репозиторий — сначала проверка .git/config, потом агент; непроверенный код — только в контейнере или VM без ваших ключей; агенты — только обновлённые. Слой «модель + классификатор + trust-промпт» в этой цепочке ничего не решает — решает то, в какой среде и с каким конфигом агент запускается.

Дальше по теме: безопасность ИИ-агентов, промпт-инъекции в кодинг-агентах, кейс: взлом auto mode, Claude Code --restricted, песочницы для ИИ-агентов, кейс: песочница агента по схеме Micah Lee.


Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка / 5. Количество оценок:

Оценок пока нет. Поставьте оценку первым.

Добавить комментарий

Adblock
detector