Разрешение шире, чем задача
Полный доступ к диску (FDA) в macOS — это единое разрешение TCC (Transparency, Consent, and Control), которое снимает барьеры песочницы на чтение по всему домашнему каталогу. На практике одно одобрение охватывает хранилище Mail, каталоги профилей Safari и Chrome, связку ключей для входа, базу данных Messages и любые учётные данные разработчика, лежащие в ~/.aws, ~/.ssh или ~/.config. Пользователь видит один диалог и один переключатель. Система видит один бит.
Этот бит долговечен. Он переживает перезагрузки, применяется к каждому будущему вызову подписанного бинарника и не сужается в зависимости от того, как был запущен процесс. Агент, которому во вторник нужно было прочитать одну папку проекта, в пятницу, когда его просят суммировать PDF из каталога загрузок, всё ещё обладает тем же разрешением.
Рабочие нагрузки агентов эпизодичны. У запуска есть начало, план, набор вызовов инструментов и конец. Разрыв между тем, что нужно запуску, и тем, что разрешает грант, — это поверхность риска, и в macOS этот разрыв сейчас равен всему домашнему каталогу.
Почему модель приложения не подходит
Классические приложения macOS имеют стабильный, поддающийся аудиту набор функций. Редактор фотографий читает изображения. Почтовый клиент читает хранилище почты. Проверяющие могут рассуждать о разрешении, потому что поведение ограничено назначением продукта.
Набор чтения агента определяется во время выполнения планировщиком. Один и тот же бинарник, вызванный дважды, может в одной сессии прочитать электронную таблицу, а в следующей — файл связки ключей, потому что план генерируется из промпта и окружения. Не существует статического манифеста, описывающего, к чему будет обращаться процесс.

Это меняет характер отказа при инъекции промпта. В обычном приложении инъекция может привести к плохому выводу. В агенте, обладающем FDA, инъекция превращает легитимный грант в путь для эксфильтрации без какого-либо повышения привилегий: модель уже авторизована читать учётные данные, а сетевой инструмент уже авторизован отправлять байты. Злоумышленнику не нужно взламывать песочницу; ему нужно направить план.
Пользователю же предлагается рассуждать о диалоге, который говорит «доступ ко всем файлам», когда задача — «суммируй эту папку». Диалог не может выразить задачу, потому что ОС не знает задачу. Поэтому согласие является неинформированным именно в том смысле, который важен: оно не ограничено рамками решения, которое пользователь фактически принимает. Освещение ужесточения Apple этих элементов управления сосредоточилось на опыте разработчиков приложений (The Verge, TechCrunch); случай агента структурно отличается, потому что запрашивающая сторона не является фиксированным набором функций.
Альтернатива с областью задачи
Управление должно перейти от бинарного разрешения ОС к контракту возможностей с областью задачи. Грант ОС становится потолком; фреймворк агента становится точкой принудительного сужения.
Конкретный механизм: выдача ограниченного дескриптора на каждый запуск. Дескриптор — это небольшая запись с четырьмя полями.
- Пути. Явный список разрешённых каталогов или файлов, разрешаемый во время планирования, а не во время выдачи гранта. Символические ссылки разрешаются, и проверяется именно разрешённый путь.
- Временное окно. Истечение по настенным часам. После него дескриптор инертен, даже если процесс всё ещё жив.
- Бюджет байтов. Совокупный лимит на чтение. Когда бюджет исчерпан, дальнейшие чтения завершаются отказом, а не молчаливым усечением.
- Терминальное состояние. Правило отзыва при завершении. Когда запуск достигает терминального состояния (успех, ошибка, тайм-аут, отмена), дескриптор уничтожается, а запись аудита запечатывается.
handle = broker.issue(
paths=["~/work/reports/q3"],
ttl_seconds=600,
byte_budget=64 * led"],
)

# every read goes through the handle, not the filesystem
blob = handle.read("~/work/reports/q3/summary.md")
Каждое чтение регистрируется на границе дескриптора, что делает аудиторский след привязанным к задаче, а не к бинарнику. Когда что-то идёт не так, вопрос «к чему обращался этот запуск» имеет прямой ответ вместо реконструкции из телеметрии уровня процесса.
Компромисс реален, и о нём стоит сказать прямо. Брокер, опосредующий чтения, добавляет компонент, который может отказать, а слишком жёсткий бюджет байтов прервёт легитимные длительные задания. Поэтому фреймворк должен предоставлять бюджет планировщику, чтобы агент мог запросить расширение до того, как упрётся в стену, а не обнаруживать лимит как исключение посреди запуска. Это больше движущихся частей, чем один переключатель TCC, и это цена того, чтобы разрешение что-то значило.
Что это означает для разработчиков агентов на macOS
Проектируйте для мира, в котором широкий грант не поощряется. Предпочитайте средства выбора документов, закладки с областью безопасности и разрешения для отдельных каталогов вместо единого одобрения FDA. Закладка, указывающая на одну папку, — более узкая возможность, чем чтение всего домашнего каталога, и её можно сохранять и повторно проверять при каждом запуске.
Исходите из того, что грант будет виден пользователю в уведомлении, и сделайте это уведомление осмысленным. Если система показывает «этот агент прочитал вашу базу данных Messages», агент должен быть в состоянии сказать, какая задача это вызвала и для чего были использованы данные. Уведомление, на которое пользователь не может отреагировать, приучает его отклонять уведомления, что ухудшает управление для всех остальных приложений.
Планируйте отзыв посреди запуска. Дескриптор может истечь, закладка может устареть, пользователь может отключить грант, пока агент работает. Агент должен быть возобновляемым, а не фатальным: сохраняйте контрольную точку плана, отмечайте шаг, потерявший свою возможность, и либо запрашивайте новый дескриптор с более узкой областью, либо чисто останавливайтесь с частичным результатом. Трактовка отзыва как сбоя превращает элемент управления безопасностью в инцидент надёжности, а именно так элементы управления и отключаются.
Более широкая мысль в том, что единица доверия должна соответствовать единице работы. Запуск агента — это единица работы. Время жизни бинарника — нет. Пока модель разрешений не отражает это, каждый агент на macOS находится в одной инъекции промпта от чтения большего, чем когда-либо требовала его задача.
