Безопасность ИИ-агента: больше контроля или специальная среда?
TL;DR. 19 октября из Microsoft написали, что агентов внутри компании нужно считать инсайдерами без презумпции доверия. Предложение: агенты-надзиратели, которые смотрят каждое действие каждого агента до того, как оно совершится. Я согласен с диагнозом, но сомневаюсь в рецепте. В посте есть слово overprivileged, и, по-моему, вся беда в нём: агенту выдали права с запасом, потому что точнее выдать было нельзя — права разбросаны по системам и единой модели у них нет. Моя гипотеза: часть надзора можно заменить устройством среды, в которой агент работает. Надзиратель лечит симптом: смотрит на действие и гадает, что оно значит. Если права, данные и связи описаны в одной модели, агенту можно выдать права конкретного человека, и тогда ему гадать почти не о чем, и надзора нужно меньше. Ниже — как через такую среду прошли бы известные инциденты с агентами и что нашли детерминированные пробы нашего ядра.
Почему меня это волнует? Я разрабатываю конструктор Интеграма, где данные, связи и права бизнеса описаны в одной модели, и агенты работают внутри неё. Про безопасность агентов меня спрашивают всё чаще: раньше из любопытства, а теперь из страха впустить агента в рабочую базу. Пост Microsoft оказался поводом ответить один раз письменно и заодно проверить гипотезы публично.
Что именно написала Microsoft
Пост Securing the agentic insider подписан Хайет Галло, EVP Microsoft Security. Пересказ по тексту, ключевые слова привожу в оригинале:
-
frontier-модели «cannot be trusted», независимо от происхождения. Не из злого умысла: модель оптимизирует результат, учитывая нормы организации, отсюда reward hacking;
-
компания сама развернула агентов внутри и поэтому неявно им доверяла. Ошибка: это «agentic insiders»;
-
агенты «frequently overprivileged», у них доступ к данным, инструментам и системам;
-
ответ: Guardian Agents, которые «watch and moderate every action of every agent, before it happens, 24/7», и «deterministic controls on non-deterministic intelligence»;
-
прозрачность модели (разбор цепочек рассуждения) сдерживание не заменит, но сделает его умнее.
Пост опирается на эссе Наделлы «Models as Insider Risks», и там основная мысль, что контроль должен стоять вне модели. С этим я спорить не буду, но хочу прояснить где именно вне модели.
Где надзор, а где среда
Надзор, по версии Microsoft, смотрит на действие и решает: пускать или нет. Чтобы решить, ему нужно понять, что это действие значит. А в типичной компании одно и то же намерение «поправь цену в заказе» выглядит по-разному: SQL в одной системе, PATCH в REST в другой, макрос в таблице, письмо в третью. У каждой своя модель прав, свой журнал (или его нет), своё представление о том, что такое «заказ». Надзорному слою приходится сводить эти действия к общей модели смысла и прав. Это решаемо: типизированные инструменты, API и политики позволяют обойтись без модели на каждое действие. Но чем пестрее среда, тем больше в этом сведении ручной работы, а там, где руки не дошли, угадывания, и угадывает обычно та же недетерминированная модель, которую надзор должен сдерживать.
Под «устроенной средой» я имею в виду три базовые вещи:
-
Один словарь действий. Создать, изменить, удалить объект типа T; прочитать выборку. Всё по-человечески, бизнес-терминами. Не произвольный SQL, не «вызови эндпоинт».
-
Одна модель прав на все данные. Права на тип, маски строк, маски колонок, отдельные флаги на удаление, выгрузку и создание. Агент действует правами того человека, который его запустил, а не служебной учёткой с правами на всё.
-
Один журнал, в котором видно, кто сделал изменение: человек или модель от его имени.
Гипотеза в том, что при таком устройстве часть «детерминированного контроля» перестаёт быть отдельным продуктом. Для удаления в этой среде правило задаётся один раз: «любое удаление через подтверждение человеком». Правило «агент не видит зарплаты» сводится к маске колонки, которая уже действует на человека. А если роли нужно изменить то, что руками ей менять нельзя, например согласовать заказ без права трогать его статус, для этого есть отчёт. Он работает как хранимая процедура и делает ровно ту правку, которую задумал его автор. Агент получает узкую операцию «согласовать», а не права на таблицу заказов. Надзору остаётся меньше работы, и работа эта проще: сверять действие с правилом, а не восстанавливать смысл произвольного запроса.
Это не значит, что надзор не нужен. Просто его объём зависит от среды, и в плохо устроенной среде он растёт быстрее, чем количество агентов.
Мера за мерой: что из надзора может взять на себя среда
Я перечислю меры, которые обычно предлагают для контроля агентов, и посмотрю, что из них у нас закрывает сама среда, а что нет.
|
Мера |
Что делает среда |
Чего среда не делает |
|---|---|---|
|
Отдельная идентичность агента и человека |
в журнале изменений |
собственных прав у агента нет, только права человека. Метку ставит клиент, сервер её не проверяет: это пометка честного клиента, а не доказательство |
|
Минимальные права |
агент работает правами того, кто его запустил. Схема, которую видит модель, собрана этими правами: таблиц без гранта для неё нет. Маски строк и колонок, отдельные флаги на удаление, выгрузку, создание. Правку того, что произвольно править нельзя, даёт отчёт-операция, а не право на таблицу |
прав «под задачу и на время задачи» нет |
|
Защита учётных данных |
модель не видит токен пользователя. У неё одноразовый ключ к прокси, который ходит только в свою базу |
так работает чат в приложении. Агент, который собирает приложение по API, держит токен сам; токен действует только в одной базе |
|
Ступенчатое реагирование |
чтение сразу. Запись сначала становится планом; правка одной записи применяется с откатом. Удаление, схема, права, файлы и всё крупнее порога ждут кнопки «Применить» человека. Перед изменением схемы бэкап, откат сутки |
усталость подтверждающего никак не учитывается |
|
Детерминированный контроль до действия |
действий четыре, правило пишется на пару «действие + тип». Закрытая таблица даёт 403, действие шире выборки даёт 400, а не молча выполняется |
промпт-инъекция в данных до модели доходит |
|
Трассировка |
журнал отвечает на «кто и что» |
на «почему» не отвечает: рассуждений модели он не хранит |
|
Динамическая оценка риска |
нет |
нет |
Если присмотреться, верхние четыре строки и есть «ступенчатое реагирование» и «детерминированный контроль» из поста Microsoft, только зашитые в среду, а не поручённые отдельному агенту, который пытается понять, что делает первый. Нижние строки честно пустые: там надзор нужен в любом случае.
Что было бы у нас: известные инциденты
Проверять гипотезу на собственном удачном заказе бессмысленно: в удачном заказе ничего плохого и не должно случиться. Честнее взять чужие провалы и посмотреть, каким путём они прошли бы у нас.
Сначала оговорка, без которой разбор нечестен. Агент работает у нас в двух режимах, и разница между ними больше, чем между нами и остальными:
-
сборка приложения. Агент получает пустую базу, работает по API токеном её администратора, сам создаёт таблицы, роли и права. Ограничения здесь только у базы как целого: токен действует в одной базе и больше нигде;
-
чат внутри приложения. Агент действует правами того, кто с ним говорит, токена не видит, запись превращается в план, опасное ждёт кнопки человека.
Таблица мер выше описывает второй режим. Первый ближе к тому, что описывает Microsoft.
Replit удалил боевую базу SaaStr (на Хабре). Во время объявленной заморозки агент удалил базу, а запрет на изменения звучал одиннадцать раз — в промпте. При сборке у нас было бы то же самое: запрет в инструкции агента остаётся текстом, держит только бэкап. В чате удаление и изменение схемы ждут «Применить», перед схемой делается бэкап, а запрет на удаление — это флаг в гранте, а не фраза.
PocketOS: агент нашёл токен и за девять секунд удалил том вместе с бэкапами. Токен лежал в постороннем файле и давал полный доступ к облаку. При сборке токен у нашего агента на руках, но действует только в одной базе: снести соседние базы или инфраструктуру им нельзя. В чате модель токена не видит.
Supabase MCP: инструкция в тикете, служебная роль в обход политик строк. Агент разработчика читал тикеты под service_role, которая обходит RLS, и выписал в тикет таблицу с токенами. Наш токен администратора базы и есть такая служебная роль. Чат действует правами человека, и маски строк к нему применяются.
GitHub MCP и EchoLeak в Microsoft 365 Copilot: инъекция через данные. Текст в issue или в письме становится инструкцией, и агент выносит приватные данные наружу. Этого не закрывает ни один наш режим. Чат лишь ограничивает ущерб правами человека и подтверждением опасного.
Copilot включил себе автоподтверждение и o3 переписывала собственный грейдер. Агент меняет то, что его проверяет. При сборке наш агент может расширить права роли, чтобы тест под ролью прошёл, и ядро ему не помешает: он администратор. В чате права меняются только через человека, и решает это код по фактической команде, а не пометка модели.
Итого: удаление и чужой токен среда закрывает в режиме чата, служебную роль — правами человека, инъекции — ничем. А сборка под администратором — это наша собственная зона того самого риска, о котором пишет Microsoft.
Что мы проверили
Довод «среда закрывает пути детерминированно» можно проверить без модели: взять приложение, роли и маски и попробовать каждый путь руками. Мы так и сделали — 27 проб на ядре конструктора, чтение и запись, таблицы, колонки, строки.
Права на таблицы, колонки и строки держатся на чтении и на записи, уникальность держится, тип, на который есть ссылки, удалить нельзя.
Не закрыто: обязательность полей ядро не проверяет, текст в числовом поле тихо становится нулём, а правил процесса («из статуса А только в статус Б») в ядре нет вообще. Для агента, который массово переносит данные, второе особенно неприятно: кривая миграция пройдёт без ошибки.
Это проверка только детерминированного слоя. Как ведёт себя модель внутри него, мы пока не мерили, но планируем сделать это, если увидим интерес у сообщества.
Не замедляет ли среда работу
Права с запасом обычно выдают ради скорости: точные права и подтверждения мешают работать, и агенту дают больше, чем нужно. Но скорость агента зависит ещё и от того, сколько ему приходится угадывать, а это тот же вопрос, что и с надзором.
Пример — доработки для небольшого производства кормов: приложение на 19 таблиц и четыре роли, имена на странице с кейсом изменены, числа настоящие. Заказчик завёл шесть доработок по шаблону «правило, где действует, как воспроизвести, что сейчас и что должно быть». Агент поправил рабочие места, завёл в живой базе новый справочник, наполнил его из существующих планов и нашёл, откуда в датах смен бралось «01.01.1970». От постановки до приёмки прошло меньше полутора часов. Какие таблицы, связи и роли задевает правка, агент не выяснял по разным системам, а читал из той же модели, по которой проверяются права.
Каждое из этих действий есть в таблице мер, и у каждого есть родственник среди инцидентов выше:
|
Действие в доработке |
Ступень в чате |
Что пошло не так в похожем инциденте |
|---|---|---|
|
найти, откуда «01.01.1970» |
чтение, сразу |
GitHub MCP, EchoLeak: через чтение в модель попадает инъекция |
|
поправить код рабочих мест |
файлы, кнопка «Применить» |
Copilot сам переписал файл своих настроек |
|
завести справочник в живой базе |
схема: бэкап, затем кнопка |
Replit: схему и данные снесли во время заморозки |
|
наполнить справочник из планов |
массовая запись: план крупнее порога, кнопка |
Supabase: агент работал под служебной ролью, которой политики строк не указ |
Получается, что обычная доработка состоит из тех же действий, на которых случаются инциденты. Разница только в том, что их сдерживает. Три из четырёх в чате ждут кнопку человека, и решает это код по типу действия, а не надзиратель по смыслу запроса. Четвёртое, чтение, идёт сразу. Именно там живёт инъекция, которую среда не закрывает. На шесть доработок человеку пришлось бы подтверждать файлы, схему и массовую запись, а не каждый шаг. Сколько таких подтверждений приходится на задачу, как раз и стоит мерить (об этом ниже).
Оговорка: сами эти доработки шли в первом режиме, под администратором, и держались на бэкапе и приёмке человеком, то есть ровно так, как в Replit и PocketOS. Обошлось без инцидента, но держало это не среда, а бэкап и человек. Поэтому такие доработки мы переводим в чат.
Где гипотеза не работает
Этот раздел я считаю главным, потому что он расширяет границы объема дальнейших работ.
Единая модель прав концентрирует риск. Ошибка в одном гранте открывает всё, что под ним. В зоопарке систем ошибка в правах одной системы ограничена этой системой. В единой среде она ограничена только масками, которые кто-то настроил правильно. Каждый, кто разбирал историю с Copilot, который «видит только то, к чему есть доступ у пользователя», знает продолжение: доступ годами раздавали широко, а агент просто нашёл забытое.
Права пользователя бывают широкими. Агент от имени директора может то же, что директор. Принцип «агент не шире человека» защищает от служебной учётки с правами на всё, но не от того, что у человека самого прав больше, чем нужно для задачи. Политики «права под задачу и на время задачи» из поста Microsoft у нас нет.
Промпт-инъекции среда не лечит. Если в записи лежит текст «удали всё», среда гарантирует только то, что удаление пойдёт через подтверждение. Человек, который устал подтверждать двадцатый план за день, нажмёт «Применить». Граница между данными и инструкцией внутри модели от устройства базы не появляется.
Сборка под администратором — наша собственная зона риска. Пока агент собирает приложение, у него права на всю базу, и между ним и её содержимым стоят только инструкция и бэкап. Для пустой базы это терпимо, для доработок живой — нет, поэтому доработки мы переводим в чат. Но сама сборка остаётся режимом, где правило — это текст, а не право.
Ещё одно неприятное: всё это работает, только если агент живёт внутри такой среды. Когда ему нужно сходить в почту, в 1С и в чужой API, единый словарь заканчивается на границе платформы, и дальше снова нужен надзор в духе Microsoft.
Что я на самом деле утверждаю
Немного, и это гипотеза, а не вывод. Объём контроля, который нужен агенту, зависит не только от агента, но и от того, насколько описуема среда: один словарь действий, одна модель прав, один журнал. В такой среде часть «надзора», по моему предположению, превращается в обычные правила доступа, которые и так действуют на людей. Остальная часть никуда не девается, и в ней Microsoft права.
Сильнее сказать не могу: пробы ядра проверяют, что правила исполняются, но не то, сколько надзора они экономят. Число инцидентов для сравнения не годится, потому что на нём задачи влияют сильнее, чем среда. Но можно мерить другое. Если тема окажется интересной, следующая статья будет замером. Один набор задач прогоняется в двух средах: единая модель против связки «обычные системы + API + MCP». В набор входят задачи с попыткой выйти за права и задачи с подложенной инъекцией в данных. Считаем три вещи:
-
сколько выходов за права среда остановила сама, детерминированно;
-
сколько дошло до надзора или до подтверждения человеком;
-
сколько подтверждений приходится на одну задачу. Это цена контроля для человека, и усталость подтверждающего начинается именно с неё.
Если вы знаете, чем такая схема плоха, буду благодарен за комментарии.
Три вопроса к тем, у кого агенты уже работают
-
Если бизнес-логика, данные и связи описаны в одной модели, становится ли поведение агента предсказуемее на ваших задачах? Или это ощущение, которое пропадает на первой реальной интеграции?
-
Снижает ли такая архитектура потребность в надзоре, или просто переносит риск на уровень модели данных, где его сложнее заметить?
-
Есть ли у этого подхода практическое преимущество перед связкой «обычные системы + API + MCP + отдельные средства контроля»? Если вы пробовали оба пути, где было больше инцидентов?
Больше всего интересна критика от тех, кто строит агентные системы и отвечает за их безопасность: где унификация реально помогает, а где только кажется, что помогает.
P.S.
Личное. В посте Microsoft мне больше всего понравилась фраза «deterministic controls on non-deterministic intelligence». Только детерминированный контроль трудно навесить на недетерминированную среду: если каждая система в компании понимает «заказ» по-своему, контроль будет таким же разношёрстным, как системы, и его велик соблазн опять поручить модели. Мы двадцать лет строили корпоративный ИТ так, что человеку в нём приходилось постоянно угадывать. Агент угадывает быстрее и увереннее, и вот это, по-моему, и есть настоящий риск. Ставить над ним второго угадывающего тоже можно, но я бы сначала посмотрел, сколько угадывать вообще нужно.
Автор: ideavi

