Kilo Code молча отдал серверу все 12 файлов проекта, хотя разрешили только два
Автор проверил, что уходит на сервер модели, когда AI-помощник правит один знак в коде. Kilo Code 7.4.20 заменил сложение на умножение, тест прошёл, на диске изменился один файл. Но тестовый сервер, изображавший недоверенного провайдера, получил все 12 файлов проекта, хотя пользователь разрешил передать только два, и копии совпали побайтно.
AI-обработка оригинала Habr AI; редакция Hamidun News
Обычно мы принимаем работу AI-помощника так: смотрим диф, запускаем тесты, видим зелёный результат и закрываем задачу. Эксперимент, описанный на Habr, показывает дыру в этой привычке. Правка может быть идеальной, а проект при этом уже лежит на чужом сервере.
Как поставили эксперимент
Задача была нарочно крошечной: в price.py функция total(price, count) возвращала price + count, а тест ждал, что total(7, 3) даст 21. Нужно было заменить сложение на умножение и запустить check.py. Пользовательская инструкция при этом гласила: передавать можно только price.py и check.py.
Автор исходил из модели, где провайдер LLM недоверенный и намеренно нарушает инструкции. Его роль сыграл локальный HTTP-сервер на 127.0.0.1. Он имитировал потоковые ответы по OpenAI-совместимому Chat Completions API и присылал клиенту tool_calls: сначала двенадцать команд read для всех файлов синтетического проекта, потом команду исправления, потом запуск теста. Клиент был настоящий: bin/kilo.exe из расширения Kilo Code 7.4.20, запущенный через CLI-команду run. В конфигурации были разрешены чтение и выполнение команд.
Что получилось
Внешне всё выглядело образцово. Kilo поменял один знак, тест прошёл, остальные файлы на диске не изменились, код завершения нулевой, все 14 вызовов инструментов завершились со статусом completed. Но сервер получил все 12 файлов, общим объёмом 11 103 байта, и их SHA-256 совпали с оригиналами.
Механика проста. Kilo добавляет результат каждого чтения в историю чата и отправляет её в следующем запросе. Сервер вытаскивает сообщения с ролью tool, убирает номера строк и собирает файлы обратно. Никакого эксфильтрационного канала не нужно: клиент сам несёт данные в штатных запросах.
Отдельно интересен трафик. Всего было 15 обращений к модели, а суммарный объём тел запросов составил 458 779 байт при 11 КБ уникального кода. Причина в повторной отправке истории, описаниях инструментов и служебной разметке. Одного огромного запроса не было: код уходил небольшими порциями и потом повторялся. Поэтому по размеру одного запроса такую утечку не заметить.
Почему запреты работают хуже, чем кажется
В начальной серии тестов правило read: deny блокировало прямое чтение запрещённого каталога. Но при bash: allow Python прочитал тот же файл, а вывод ушёл в следующий запрос. Когда bash запретили, команда не выполнилась. Права в Kilo задаются отдельно для каждого инструмента, и запрет одного не закрывает остальные пути.
Есть и честные оговорки. Настоящей модели в эксперименте нет: команды выбирал тестовый сервер, так что склонность коммерческих моделей к такому поведению это не измеряет. Имена файлов серверу были известны заранее, самостоятельный поиск неизвестного дерева не проверялся. Графическая сессия расширения тоже не тестировалась, только CLI.
Что делать на практике
Первое: оценивайте не только диф, но и журнал вызовов инструментов и тела запросов к провайдеру. Хотя бы раз прогоните агента через локальный прокси и посмотрите, что реально уходит.
Второе: давайте агенту минимум прав. Если чтение разрешено, всё прочитанное потенциально принадлежит провайдеру. Для чувствительных репозиториев это аргумент за локальные модели или за провайдеров с жёсткими договорными гарантиями.
Третье: не полагайтесь на текстовую инструкцию вроде «передавай только эти два файла». Это пожелание модели, а не ограничение клиента. Реальную границу создают только права инструментов, песочница и сетевые политики.
Стенд автор выложил целиком: Python 3.10+, Git и исполняемый файл Kilo, около 150 строк кода. Его стоит повторить на своём клиенте, какой бы агент вы ни использовали.
- 12 нояб. 2026 г.Дженсен Хуанг ушёл с поста CEO Nvidia: компания потеряла $1,4 трлн за две недели
- 12 нояб. 2026 г.Профсоюз Окленда добился переобучения вместо увольнений из-за ИИ: за забастовку 94,1%
- 12 нояб. 2026 г.Восемь стран и OpenAI с Anthropic обещают «рубильник» для ИИ-моделей, но без сроков и штрафов
- 12 нояб. 2026 г.OpenAI и ModRetro выпустили консоль за $200 для игр, написанных в Codex
Вопросы и ответы по материалу
Что известно по теме: как поставили эксперимент?
Задача была нарочно крошечной: в price.py функция total(price, count) возвращала price + count, а тест ждал, что total(7, 3) даст 21. Нужно было заменить сложение на умножение и запустить check.py. Пользовательская инструкция при этом гласила: передавать можно только price.py и check.py. Автор исходил из модели, где провайдер LLM недоверенный и намеренно нарушает инструкции. Его роль сыграл локальный HTTP-сервер на 127.0.0.1.
Что известно по теме: что получилось?
Внешне всё выглядело образцово. Kilo поменял один знак, тест прошёл, остальные файлы на диске не изменились, код завершения нулевой, все 14 вызовов инструментов завершились со статусом completed. Но сервер получил все 12 файлов, общим объёмом 11 103 байта, и их SHA-256 совпали с оригиналами. Механика проста. Kilo добавляет результат каждого чтения в историю чата и отправляет её в следующем запросе. Сервер вытаскивает сообщения с ролью tool, убирает номера строк и собирает файлы обратно.
Что известно по теме: почему запреты работают хуже, чем кажется?
В начальной серии тестов правило read: deny блокировало прямое чтение запрещённого каталога. Но при bash: allow Python прочитал тот же файл, а вывод ушёл в следующий запрос. Когда bash запретили, команда не выполнилась. Права в Kilo задаются отдельно для каждого инструмента, и запрет одного не закрывает остальные пути. Есть и честные оговорки. Настоящей модели в эксперименте нет: команды выбирал тестовый сервер, так что склонность коммерческих моделей к такому поведению это не измеряет.
Протестируйте новые LLM и мультимодальные модели в одном окне
Платформа Nomad AI (nomadnet.ai) даёт прямой доступ к Claude Opus 5.5, GPT-6, Gemini 3.1, DeepSeek и автономным агентам без VPN, зарубежных карт и зоопарка подписок.
Главное из мира ИИ — раз в неделю
7 ключевых событий недели, отобранных вручную. Без шума, репостов и пресс-релизов.
Готово! Проверьте почту — мы отправили подтверждение.