Least-privilege — одна из старейших и самых надёжных идей в безопасности. Дайте идентичности ровно тот доступ, который ей нужен, и ничего больше, и радиус поражения при любой компрометации останется небольшим. Для пользовательских учётных записей и долгоживущих сервисных аккаунтов эта модель держится вполне неплохо: роли проверяются, гранты ограничиваются по области действия, сертификация доступов проводится с ежеквартальной периодичностью.
AI-агенты тихо ломают эту модель. Агенту выдают учётные данные, инструмент, подключение к MCP-серверу — и с этого момента его поведение становится динамическим. Он решает в рантайме, какие ресурсы читать, какие писать, какой инструмент вызвать следующим. Грант, который вы записали в первый день, описывает потолок, а не то, что агент делает. А поскольку агенты продуктивны, этот потолок обычно ставят с запасом: широкие роли в базе данных, доступ на запись «на всякий случай», сервисный аккаунт, общий для полудюжины рабочих процессов. В итоге получается ландшафт, где разрешённый доступ и фактически используемый доступ расходятся — тихо, каждый день.
Независимые отраслевые исследования отражают масштаб этого слепого пятна: примерно 82% организаций сообщают, что у них работают AI-агенты, о которых они не знали (CSA/Token Security, n=418). Вы не сможете применить least-privilege к ландшафту, который не видите.
Определение дрейфа от least-privilege
Дрейф от least-privilege — это растущий разрыв между доступом, который агенту разрешён, и доступом, который он, как наблюдается, использует. У него есть два направления сбоя, и очевидно только одно из них.
Очевидное направление — это недоиспользование: агент держит доступ на запись к таблице, в которую ни разу не писал. Это мёртвая привилегия, и это риск, который вы несёте без какой-либо выгоды. Опасное направление — это обратный сигнал, который оно подразумевает: когда наблюдаемое множество содержит то, что разрешённое множество никогда намеренно не предоставляло, у вас есть действие, которое никто не проверял. Задание экспорта, которое внезапно пишет в бакет, из которого оно только читало. Агент, которому политика ограничила область одной схемой, дотягивается до другой. Это не экзотика; это повседневная фактура агентов, связанных между собой грубыми грантами.
Причина, по которой это сложно, и причина, по которой это специфично именно для агентов, а не для людей, в том, что поведение генерируется, а не конфигурируется. Человек с избыточным доступом по большей части его не использует. Агент с избыточным доступом использует всё, что помогает ему выполнить стоящую перед ним задачу, включая пути, которых никто не предвидел. Статическая проверка политик не успевает за поведением, которое меняется от запуска к запуску.
Превращение дрейфа в проверяемый сигнал
Дрейф опасен лишь пока он невидим. Задача — превратить его в сигнал, который человек может проверить, а для этого нужны две вещи, работающие вместе: непрерывное наблюдение за тем, к чему агенты на самом деле обращаются, и стабильная запись того, к чему им было разрешено обращаться.
Наблюдение должно вестись в режиме read-first. Сборщик, который наблюдает из логов, трейсов OpenTelemetry и сигналов ядра eBPF, находится вне пути данных агента. Это не прокси, он не пропускает вызовы через себя, и если он отказывает, то отказывает «открыто» в безопасном смысле: агент продолжает работать, вы теряете видимость, а не доступность. Эта асимметрия важна: средство защиты, способное положить прод, — это средство, которое команды тихо отключают. Слой eBPF, в частности, выступает как ground truth на уровне ядра — та часть, которую агент не может обойти (перехват на уровне ядра обеспечивает датчик Tetragon, который вы разворачиваете сами; Olivares AI читает экспорт Tetragon и сам не загружает eBPF-программы), — и именно поэтому подсказки на уровне протокола, такие как аннотации инструментов MCP (readOnlyHint, destructiveHint), сверяются с ним, а не принимаются на веру. Сама спецификация MCP говорит, что этим аннотациям доверять нельзя; сигналы ядра — это то, что делает такую сверку реальной.
Результатом наблюдения является карта доступа: для каждого агента — к каким ресурсам он обращался и читал ли он (R) или читал и писал (RW). Карта хранит отношения доступа, а не полезные нагрузки, секреты или PII. Интересная часть — это сравнение:
| Агент | Ресурс | Разрешено | Наблюдается | Дрейф |
|---|---|---|---|---|
| data-export-job | prod-postgres | R | R | нет |
| data-export-job | s3://billing-exports | R | RW | непроверенная запись |
| report-builder | analytics-db | R | (не используется) | мёртвая привилегия |
Значимая строка — средняя. Политика дала чтение бакета экспорта; сборщик наблюдал запись. Эта единственная строка — главный риск, который дрейф от least-privilege и призван выявить: задействованная привилегия, которую никто не проверял, отнесённая к конкретному агенту, а не к общему сервисному аккаунту, потому что именно идентичность на уровне отдельного агента вообще делает возможными атрибуцию и аудит.
Применение в момент доступа, а не просто логирование
Обнаружение говорит вам, что дрейф произошёл. Чтобы замкнуть цикл, вы хотите, чтобы непроверенная запись стала запрещённым путём, а не залогированным. Здесь и вступает в дело политика, оцениваемая в момент доступа.
Olivares AI оценивает Cedar как оверлей forbid поверх ролей с запретом по умолчанию, поэтому правило может только отнимать доступ; это правило отклоняет любой запрос, который затрагивает секретные учётные данные, что бы ни говорила роль.
permit(principal, action, resource);
forbid(principal, action, resource)
when { resource.kind == "credential" && resource.sensitivity == "secret" };
Писать собственные правила Cedar можно с Business; Community применяет встроенные роли, нативный оверлей запрета и kill switch; собственные роли и ограниченные по области гранты входят в Business.
Пройдём «до» и «после» конкретно.
До. Кодинг-агент, обладая широкой ролью, вызывает инструмент MCP, который пишет в s3://billing-exports. Ничто его не останавливает. Действие проходит успешно, сливается с обычным трафиком и проявляется днями позже, если вообще проявляется, как аномалия на карте доступа. Разрыв между разрешённым и наблюдаемым расширился, а единственный артефакт — строка лога, которую никто не прочитал.
После. Тот же вызов инструмента доходит до шлюза MCP. Роль агента не разрешает эту запись, поэтому шлюз отклоняет вызов до его выполнения (deny-closed) и фиксирует отказ в подписанном журнале аудита, в котором любое вмешательство обнаруживается. Непроверенная запись так и не становится непроверенным изменением. Olivares AI блокирует действие только в четырёх точках применения: внутри Claude Code, в прокси модели, при каждом вызове инструмента MCP и между агентами. Задание, которое пишет в S3 напрямую, в обход этих точек, не блокируется: карта доступа фиксирует запись и помечает её как дрейф для проверки.
Два свойства сохраняют честность этого подхода. Во-первых, каждый привилегированный просмотр карты доступа сам подвергается аудиту — кто и на что смотрел, — потому что карта чувствительна, а средство защиты, которое не может отчитаться за собственных операторов, не заслуживает доверия. Во-вторых, уверенность показывается явно: ребро, источник которого несёт идентификатор отдельного агента, помечается attributed, а ребро, замеченное только ядром, — approximate, потому что сигналы ядра называют процесс, cgroup или контейнер, а не агента. Вас никогда не просят действовать на основании сфабрикованной уверенности.
Вывод
Least-privilege не подвёл для AI-агентов; подвела периодичность проверок. Гранты грубы, поведение динамично, а ежеквартальные сертификации не могут отслеживать поверхность доступа, которая меняется от запуска к запуску. Решение — не более тяжёлый прокси на критическом пути. Это непрерывное наблюдение в режиме read-first, которое формирует сравнение «разрешено vs наблюдается», плюс policy-as-code, который применяет исправленную границу в момент доступа, — так что чрезмерно привилегированный агент обнаруживается как проверяемый сигнал задолго до того, как он превратится в инцидент.
Если вы хотите увидеть, как сборщик, карта доступа и применение в момент доступа складываются вместе, не находясь на пути данных ваших агентов, страница архитектуры разбирает дизайн, а продукт показывает, как выглядит представление «разрешено vs наблюдается» на реальном ландшафте.