Практическое руководство по минимально необходимому доступу для ИИ-кодовых агентов

Большинство настроек ИИ-кодовых агентов начинаются с credential, дающего всё, на что способен базовый аккаунт, потому что ограничить его требует дополнительной работы, которую никто не делает в первый день. Это не редкая ошибка конфигурации. Это дефолт, и он остаётся дефолтом, пока что-то не заставит его поменять, ровно так агент нашёл неродственный API-токен и снёс продовую базу данных за девять секунд: найденный им credential был широким, потому что широкий доступ это обычно и есть дефолтная настройка доступа агента.
Принцип наименьших привилегий не новая идея. Применение его к тому, что действует автономно, на скорости машины, без человека, подтверждающего каждый шаг, это как раз то место, где старому совету нужны конкретные паттерны, а не повторение принципа.
Ограничивать по риску действия, а не только по ресурсу
«Этот агент может обращаться к этому репозиторию» это ограничение на уровне ресурса. Оно ничего не говорит о том, какие действия внутри этого репозитория безопасно выполнять без присмотра, а какие требуют сначала подтверждения человеком. Более полезное ограничение разделяет действия по тому, что произойдёт, если агент ошибётся:
- Обратимые, дешёвые действия: чтение файлов, прогон тестов, открытие черновика PR, комментарий к тикету. Безопасно разрешать автоматически, потому что ошибку здесь можно отменить за пару минут.
- Обратимые, но более дорогие действия: мёрдж PR, перевод тикета в Done, изменение общего конфигурационного файла. Стоят более лёгкой проверки, не обязательно полной остановки, потому что цена ошибки уже реальна, но всё ещё поправима.
- Деструктивные или трудно обратимые действия: удаление данных, force push, ротация credentials, изменение продовой инфраструктуры. Это ровно те действия, которые в принципе не должны быть достижимы из дефолтного скоупа агента, не спрятаны за подтверждением, которое агента можно уговорить обойти, а структурно отсутствуют в том, что способен сделать credential.
Удаление в PocketOS целиком попадает в третью категорию, и реальным провалом было не то, что агент плохо выбрал под давлением. Дело в том, что деструктивная мутация в Railway вообще была достижима из credential, предназначенного для фикса в staging.
Ограничивать по окружению явно
Credential, работающий в staging, и credential, работающий в продакшене, не должны быть одним и тем же credential, и это должно быть верно даже когда одному и тому же агенту законно нужно трогать оба окружения в разное время. Инцидент PocketOS это прямой контрпример: задача, ограниченная staging, имела действующий путь к ресурсу, ограниченному продакшеном, потому что границы окружений не были принудительно заданы на уровне credential, а только подразумевались на уровне задачи.
Это дёшево сделать правильно и дорого исправлять постфактум после инцидента. Отдельные credentials на каждое окружение, выпускаемые на задачу, а не хранящиеся бессрочно, означают, что агент, работающий над багом в staging, просто не может дотянуться до продакшена, не потому что ему это запретили, а потому что credential, которым он владеет, туда попросту не резолвится.
Ограничивать по времени
Credential, действующий бессрочно, это credential, всё ещё действующий задолго после того, как задача, под которую он выдан, завершена, а это ровно тот вид устаревшего, широкого доступа, до которого в итоге дотягивается что-то, чему до него дела быть не должно. Короткоживущие credentials, привязанные к задаче и истекающие вместе с ней, сужают окно, в котором чрезмерно широкий доступ может быть использован не по назначению, будь то агентом, которому он был выдан, или чем-то ещё, что до него сумело дотянуться.
Как это выглядит в виде референсного паттерна
MCP-токены TAM это одна конкретная версия такого подхода, и стоит разобрать её подробно, потому что скоупинг живёт в самом токене, а не в политике, соблюдение которой кто-то обязан помнить: токен несёт явный список allowedTools и явный список allowedProjects в момент выпуска, привязанный к собственному аккаунту конкретного агента, а не к общему credential. Агент, подключённый с этим токеном, не может вызвать инструмент вне allowedTools или тронуть проект вне allowedProjects, не потому что политика это не приветствует, а потому что токен это попросту не авторизует. Это тот же структурный ответ, которого сегодня не дают собственные MCP-серверы Jira и Linear: оба аутентифицируют агента как аккаунт подключившегося человека, без скоупа на агента уже того, что мог бы сделать этот человек. Ещё одна причина, почему самому MCP-серверу нельзя доверять по умолчанию, а нужно это доверие проверять.
Принцип наименьших привилегий для автономного агента это не документ с политикой. Это то, что способен авторизовать сам credential, проверенное в момент выпуска, а не то, что человек не забыл сказать агенту не делать.