Иногда новость хочется начать не с технического вступления, а с короткого и честного: ахуеть.

Почему это важно до установки CLI#

CLI для AI-разработки запускается рядом с кодом, секретами, историей коммитов и локальными конфигами. Если такой инструмент без ясного предупреждения отправляет весь репозиторий наружу, это уже вопрос доверия и границ доступа.

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

На Hacker News обсуждают wire-level разбор Grok Build CLI — официального coding CLI от xAI. Автор поднял mitmproxy, прогнал grok 0.2.93 на своём тестовом репозитории с фейковыми canary-секретами и посмотрел, что реально уходит на сервера xAI.

И вот тут важно не скатиться в красивую панику. Разбор не доказывает, что xAI обучает модели на этих репозиториях. Это отдельный policy-вопрос. Зато он показывает вещь, которой уже достаточно для холодка по спине: передача, приём и хранение кода происходят шире, чем пользователь может ожидать от обычного «агент прочитал нужный файл».

Что нашли#

Коротко: Grok Build CLI отправляет не только содержимое файлов, которые агент читает в ходе задачи.

По разбору, есть два разных канала:

  1. Модельный запрос — когда агент читает файл, его содержимое уходит в POST /v1/responses. В тесте .env / secrets.env с фейковыми canary-секретами ушёл verbatim, без редактирования. Это неприятно, но ожидаемо: если облачный агент прочитал файл, файл попадёт в облако.
  2. Отдельный storage-upload — Grok собирает snapshot репозитория и отправляет его через POST /v1/storage. Вот это уже другой класс проблемы.

Самый сильный кусок: автор дал промпт в духе «ответь OK, не читай никакие файлы». Агент ответил OK. При этом в фоне ушёл git bundle, запрос приняли с HTTP 200, а после git clone из этого bundle восстановился файл src/_probe/never_read_canary.txt — тот самый, который агенту сказали не открывать. Плюс полная git-история.

На большом тесте тоже интересно: репозиторий на 12 ГБ из случайных файлов, которые агент не читал. В /v1/storage успело уйти 5,10 GiB до остановки capture, все storage-запросы вернулись 200. В /v1/responses за ту же сессию ушло всего 192 КБ. Разница примерно в 27 800 раз.

Это уже не «модель получила контекст». Это похоже на отдельный механизм выгрузки codebase.

Почему это не то же самое, что «любой агент видит код»#

Да, cloud coding agent без отправки кода в облако почти бесполезен. Если вы запускаете Claude Code, Codex, Cursor, Grok Build или любой похожий инструмент против репозитория, вы уже соглашаетесь на то, что часть кода уйдёт провайдеру.

Но есть разница между:

  • «агент отправил файлы, которые нужны для ответа»;
  • «агент отправил весь tracked codebase вместе с git history, хотя его попросили ничего не читать».

Первая модель хотя бы укладывается в понятную границу: агент видит то, что использует. Вторая расширяет blast radius до всего, что попало в историю репозитория.

И вот это уже больно.

Потому что в git history обычно живёт не только текущий аккуратный код. Там живут старые .env, временные токены, внутренние заметки, куски архитектуры, клиентские названия, экспериментальные прототипы, забытые конфиги и всё то, что «потом перепишем нормально».

Если инструмент собирает git bundle, он забирает не только сегодняшнее состояние. Он забирает память проекта.

«Improve the model» — это не кнопка «не отправлять код»#

Отдельный неприятный момент из разбора: выключение «Improve the model» не остановило upload.

После отключения настройки /v1/settings всё равно возвращал:

{
  "trace_upload_enabled": true,
  "upload_enabled": true,
  "session_registry_enabled": true,
  "max_upload_file_bytes": 1073741824
}

То есть opt-out, судя по тесту, относится к обучению / улучшению модели, а не к факту выгрузки и хранения репозитория. Это принципиально разные вещи.

Ответ «мы не используем это для обучения» сам по себе не закрывает вопрос. Если CLI всё равно складывает снимок репозитория в grok-code-session-traces, спокойнее от этого не становится: код уже покинул машину.

Про секреты: не только .env#

В статье про утечки секретов я уже писал простое правило: всё, что вы вставили наружу, считается скомпрометированным.

С агентами граница стала хуже. Теперь секрет может уехать не потому, что вы руками вставили его в чат, а потому что он лежал рядом с кодом и инструмент решил собрать больше, чем нужно.

Тут важно не наврать. В разборе .env был tracked-файлом и читался в тестовом сценарии. Это не доказывает, что любой ignored .env всегда уезжает в snapshot всего репозитория. Но для практической безопасности разница слабое утешение:

  • если секрет лежит в tracked file — он в зоне риска;
  • если секрет когда-то был в git history — он в зоне риска;
  • если агент реально прочитал локальный файл с секретом — он в зоне риска;
  • если вы не знаете, что именно CLI выгружает, вы не можете нормально оценить риск.

И да, «секреты не должны лежать в репозитории» — правильный ответ. Но он не отменяет вопрос к инструменту: почему он молча тащит весь репозиторий и историю, когда для ответа это не нужно?

GitHub, Copilot, Claude, OpenAI — а они что?#

В обсуждении быстро всплыл стандартный аргумент: «да все они так делают», «GitHub всё отдаёт Copilot», «OpenAI и Anthropic тоже видят код».

Тут нельзя делать ложную эквивалентность.

Любой облачный агент — риск. У любого провайдера нужно читать data policy, смотреть enterprise/ZDR-варианты, понимать retention, проверять, что уходит в логах и telemetry. Если вы пускаете агент в приватный репозиторий, вы уже расширяете доверенный контур.

Но это не значит, что все механизмы одинаковые.

Нормальная граница должна быть явной и проверяемой: какие файлы читаются, что отправляется в модель, что пишется в storage, как долго хранится, что отключает opt-out, что доступно в enterprise-режиме. Если вместо этого у нас «вроде агент не читал файлы, но git bundle улетел в GCS» — это не «обычная цена прогресса». Это инженерный красный флаг.

Что делать перед запуском любого нового coding agent#

Не только Grok Build. Любого.

  1. Не держите секреты в репозитории. Ни в .env, ни в тестовых конфигах, ни в «временном» JSON. Секрет должен жить в secret manager, локальном vault или в отдельном файле, который агент не получает как контекст.

  2. Проверьте историю, а не только текущую папку. Минимальный набор:

    gitleaks detect --source .
    trufflehog git file://. --only-verified
    

    Если секрет уже был в истории, простое удаление файла не лечит проблему. Секрет нужно ротировать.

  3. Для нового CLI сначала делайте throwaway-репозиторий. Положите canary-файл, запретите агенту его читать, посмотрите сеть и локальные очереди. Не тестируйте новую игрушку сразу на клиентском monorepo.

  4. Ограничивайте outbound. Контейнер, firewall, proxy, логирование. Если инструмент реально нужен в чувствительном контуре, его сетевое поведение должно быть измеримым, а не «ну вроде нормально».

  5. Не полагайтесь только на .gitignore. Ignore-файлы помогают не закоммитить мусор. Но это не security boundary для инструмента, который может читать файловую систему или собирать snapshot по своим правилам.

  6. Давайте агенту минимальный рабочий набор. Отдельный worktree, вырезанный репозиторий, временная копия без истории, узкий токен, короткий TTL. Если задачу можно решить на маленьком фрагменте — не отдавайте весь проект.

  7. После сомнительной сессии ротируйте секреты. Не «удалил файл и забыл», а именно rotate. Всё, что могло покинуть машину, считается засвеченным.

Я ровно поэтому в работе с агентами отдельно держу правило: секреты не в чат, доступы временные, после задачи ротация, а границы полномочий прописываются заранее. В статье про Hermes Agent как инженерного исполнителя это уже всплывало: агент полезен только там, где у него есть рамка. Без рамки это не инженер, а очень быстрый способ разнести blast radius.

Итог#

AI-агенты для разработки никуда не денутся. И я не собираюсь делать вид, что «локальная модель на ноутбуке» сегодня заменяет все облачные инструменты. Не заменяет.

Но граница должна быть честной.

Если я запускаю coding agent в репозитории, я хочу понимать: вот это он отправляет в модель, вот это пишет в storage, вот это можно отключить, вот это не хранится, вот это покрыто enterprise-политикой. Без этого разговор «зато модель умная и цены хорошие» выглядит странно.

Потому что умная модель — это отлично. Но когда вместе с запросом уезжает весь репозиторий с историей, первая реакция всё равно одна.

Ахуеть.

Источники: wire-level разбор, основной тред на Hacker News, отдельная ветка комментария.

Если команда уже использует агентские CLI рядом с приватным кодом, не стоит ограничиваться доверием к красивому названию инструмента. Напишите мне в Telegram или на почту — помогу проверить сетевое поведение, права доступа и реальные артефакты upload/download, чтобы понять, что именно уезжает наружу.