Как сравнить блокировку хранилища и экрана в тесте агента
Практический план тестирования блокировки хранилища и экрана для разработчиков macOS, которым нужно доказать, что AI-агент не может использовать учетные данные после запрета.

Заблокированный экран и заблокированное хранилище решают разные задачи. Если считать их одним и тем же контролем, тест почти ничего не покажет. Блокировка экрана macOS ограничивает интерактивный доступ к пользовательской сессии. Блокировка хранилища должна останавливать защищенные действия в момент использования учетных данных, включая действия, которые запрашивает процесс, одобренный еще до вашего ухода.
Эта разница особенно важна для автономных агентов программирования. Агент может поддерживать процесс активным, сохранять контекст, планировать работу и повторять неудачный запрос. Тест, который лишь подтверждает, что человек не может печатать на рабочем столе, не показывает, способен ли этот процесс по-прежнему вызвать API или открыть SSH-соединение. Проверьте оба состояния независимо, а затем проверьте их сочетание.
Я видел, как команды называли это тестом «заблокированного компьютера», делали один снимок экрана блокировки и объявляли работу законченной. Это подтверждает наличие экрана блокировки. Но это не доказывает абсолютную границу запрета для учетных данных.
Заблокированный экран не определяет, может ли процесс действовать
Блокировка экрана macOS защищает консольную сессию от человека, у которого есть физический доступ к клавиатуре и дисплею. Сама по себе она не описывает каждый процесс, уже работающий в этой сессии, каждое принадлежащее ему сетевое соединение или каждое хранилище учетных данных, которым может пользоваться приложение.
В документации Apple по безопасности платформы аутентификация пользователя и защита сессии рассматриваются отдельно от защиты секретов, например элементов связки ключей. Это разделение полезно и здесь, даже если в вашей конфигурации меньше компонентов, чем описано у Apple. Вопрос «был ли экран заблокирован?» отличается от вопроса «мог ли агент использовать учетные данные?». Для них нужны разные доказательства.
Агент может быть безвредным при разблокированном экране и все равно представлять угрозу после того, как в его окружении появился токен доступа. И наоборот, агент может работать в заблокированной сессии, но не иметь возможности выполнить защищенный запрос, если учетные данные никогда не попадали в его память, а шлюз действий отклоняет запрос. По состоянию экрана нельзя понять, какая схема используется.
На проверке используйте такое практическое определение:
- Блокировка экрана управляет интерактивным использованием Mac.
- Блокировка хранилища определяет, может ли выполниться защищенное действие.
- Авторизация сессии определяет, может ли конкретный процесс агента запрашивать защищенные действия в течение своей работы.
- Ключ для каждого вызова определяет, должен ли человек одобрять конкретное использование учетных данных.
В удачной демонстрации эти средства могут работать согласованно. В рабочей среде безопасность не должна зависеть от такой синхронности.
Для шлюза хранилища нужен тест абсолютного запрета
Абсолютный шлюз хранилища означает, что при заблокированном хранилище отклоняется любое действие, использующее сохраненные учетные данные. Запрет должен срабатывать до подстановки учетных данных в HTTP и до аутентификации помощника SSH. Он должен распространяться и на процесс, который уже успешно выполнял действия, а не только на новый процесс, которому еще никогда не доверяли.
Sallyport явно задает эту границу: пока его хранилище заблокировано, отклоняются все действия. На поддерживаемом оборудовании macOS шлюз хранилища аппаратно защищен с помощью Secure Enclave и Touch ID. Это надежнее и понятнее, чем условное правило «агент не должен вызывать этот инструмент, пока меня нет рядом».
Самый показательный тест начинается с успешного действия. Настройте один контролируемый ресурс с незначительными последствиями, например HTTP-конечную точку, которая записывает только метод запроса и непрозрачный идентификатор, или SSH-хост с командой, выводящей фиксированное слово. Не начинайте с конечной точки рабочего развертывания. Вам нужен ресурс, журналы которого можно проверить, не раскрывая действующий секрет и не меняя ничего важного.
Затем оставьте процесс агента запущенным, заблокируйте хранилище через приложение и снова запросите то же действие. Корректный результат состоит из трех частей:
- Вызывающая сторона получает ясный отказ, а не тайм-аут или обычную сетевую ошибку.
- Журнал Activity записывает попытку как отклоненную и содержит достаточно сведений для идентификации сессии и пути к учетным данным, но не самих учетных данных.
- Контролируемая HTTP-конечная точка или SSH-хост не получают нового запроса или команды.
Третья часть выявляет ошибку, которую скрывает аккуратный интерфейс. Шлюз может показать отказ уже после отправки аутентифицированного запроса, если проверка стоит не на том уровне. Удаленный журнал становится главным свидетельством.
Для SSH не используйте тест вроде ssh host true, если тестовый хост принимает другие идентификаторы из вашей обычной среды. Используйте канал, которым воспользовался бы агент, обращайтесь к изолированной учетной записи и задайте команду, появление которой в серверных журналах невозможно спутать с другими. Если нельзя доказать, какой идентификатор установил соединение, вы проверяете настройки оболочки, а не границу хранилища.
Предыдущее разрешение не должно переживать закрытие шлюза
Авторизация сессии отвечает на более узкий вопрос: может ли этот процесс агента использовать защищенные действия во время текущего запуска? Это не постоянное разрешение, и оно не может отменить блокировку хранилища.
Здесь команды часто путают удобство и полномочия. Они одобряют агента, видят несколько успешных вызовов, блокируют хранилище, а потом разблокируют его. Когда процесс продолжает работу, они решают, должно ли прежнее разрешение сохраниться или исчезнуть, исходя из того, какой вариант кажется удобнее. Это поведение нужно определить по реальной модели управления доступом, а затем проверить. В документированной последовательности решений приложения шлюз хранилища имеет высший приоритет. Закрытый шлюз всегда побеждает.
Выполните эту последовательность, не перезапуская агента:
- Запустите новый процесс агента и выполните один защищенный вызов. Когда появится запрос, одобрите сессию.
- Выполните второй защищенный вызов с теми же обычными учетными данными. Убедитесь, что он проходит без новой карточки сессии.
- Заблокируйте хранилище, пока процесс продолжает работать. Повторите вызов и убедитесь, что он отклонен до получения запроса удаленным ресурсом.
- Разблокируйте хранилище требуемым локальным действием. Повторите вызов и зафиксируйте, возобновляется ли уже созданная сессия по документированным правилам.
- Завершите процесс агента, запустите новый процесс и выполните тот же вызов. Убедитесь, что новый запуск получает собственную карточку авторизации.
Четвертый шаг не сводится к внешнему виду. Он показывает, не начал ли продукт считать, что «хранилище открыто» означает «весь работающий код снова заслуживает доверия». Пятый шаг показывает, не превратился ли идентификатор процесса, родительский терминал или неточная метка клиента в непреднамеренно долгосрочное разрешение.
В карточке разрешения сначала должны быть указаны полномочия подписи кода процесса. Имя процесса легко скопировать. Путь может вводить в заблуждение. Полномочия подписи кода дают оператору более надежную основу для оценки запроса агента на использование секрета. Запишите, что показывала карточка во время теста, включая то, что вы увидели бы при таком же запросе от ненадежной копии клиента.
Тест блокировки экрана нужен для другой цели
Проверяйте блокировку экрана macOS после того, как установите поведение хранилища. Ее задача другая: понять, что может продолжаться, пока у консоли никого нет, и как вернуть контроль.
Сначала оставьте хранилище в предполагаемом доступном состоянии и запустите сессию, которая уже получила разрешение. Запустите одно безопасное защищенное действие, заблокируйте экран macOS, подождите достаточно долго, чтобы проверить обычный сценарий работы без присмотра, затем выясните, могло ли действие продолжиться. Не угадывайте ответ заранее. На него влияют настройки питания Mac, состояние сети, жизненный цикл процесса и собственный шлюз приложения.
Затем повторите эксперимент, но явно заблокируйте хранилище до блокировки экрана. Результат должен быть проще: попытки защищенных действий отклоняются. Если агент продолжает генерировать текст или редактировать локальные файлы, это выходит за рамки данного узкого утверждения. Проверяется, что он не может превратить сохраненный API- или SSH-ключ во внешнее действие.
Эта пара тестов отделяет неприятный, но допустимый выбор политики от уязвимости. Одни разработчики намеренно разрешают уже одобренному агенту продолжать безопасную работу при заблокированном экране. Другие требуют блокировать хранилище при каждом уходе. Это рабочие решения. Возможность агента использовать учетные данные после блокировки хранилища означает сбой границы безопасности.
Не проверяйте это, просто наблюдая экран блокировки из другого конца комнаты. Зафиксируйте время запроса агента, события на контролируемой конечной точке и записи журнала Activity. Запрос, начавшийся до блокировки экрана, может завершиться после нее. Это не доказывает, что он начался уже после блокировки. Важна последовательность событий.
Подтверждение каждого вызова нужно для действий, которые опасно одобрять оптом
Ключ с подтверждением каждого вызова требует одобрения человека при каждом использовании учетных данных. Он должен работать поверх одобренной сессии, а не заменять проверку сессии и не ослаблять шлюз хранилища.
Включите в план теста хотя бы одни такие учетные данные, даже если для большинства ключей используется обычное подтверждение сессии. Выберите действие с заметным, обратимым результатом, например тестовую конечную точку, увеличивающую одноразовый счетчик, или SSH-команду, создающую файл во временной папке. Нужно доказать, что приложение снова запрашивает подтверждение при втором использовании, а отказ в запросе предотвращает внешнее действие.
Выполните следующий тест при разблокированном экране, чтобы отделить поведение запросов от состояния сессии:
- Запустите новый процесс агента и одобрите его сессию.
- Используйте учетные данные с подтверждением каждого вызова и одобрите этот вызов. Убедитесь, что произошло одно удаленное событие.
- Снова вызовите те же учетные данные и отклоните запрос на подтверждение. Убедитесь, что второго удаленного события нет.
- Заблокируйте хранилище и вызовите их еще раз. Отказ шлюза хранилища должен произойти без предложения осмысленно одобрить действие, которое шлюз не может разрешить.
Популярная рекомендация настроить подтверждение каждого вызова для всех учетных данных кажется разумной, потому что превращает каждое действие в заметное решение. На практике люди привыкают одобрять повторяющиеся карточки, не читая их. Оставьте такой режим для учетных данных, каждое использование которых меняет состояние денег, доступа, публикации или другую важную для вас область. Для обычных вызовов осмысленное подтверждение сессии и блокируемое хранилище оставляют оператору меньше, но более понятных решений.
Удаленный журнал выявляет отказ, который не виден в локальном тесте
Локальное сообщение об ошибке доказывает лишь то, что вызывающая сторона увидела ошибку. Оно не доказывает, что аутентифицированный запрос не покинул компьютер, и ничего не говорит о повторных попытках, которые могли прийти позже.
Создайте тестовый ресурс, который сообщает короткий идентификатор запроса, выбранный вами. Действие агента может отправлять безвредный заголовок или поле тела запроса, например test_run=screen-vault-01, если настроенный путь к учетным данным шлюза допускает такую форму запроса. На принимающей стороне записывайте время получения, метод, имеющиеся у вас сведения об источнике и этот идентификатор. Изолируйте ресурс от рабочих данных.
В записи теста должна быть небольшая таблица вроде этой:
| Попытка | Состояние хранилища | Экран macOS | Ожидаемое удаленное событие | Наблюдаемый результат |
|---|---|---|---|---|
| A | доступно | разблокирован | одно событие | событие записано |
| B | заблокировано | разблокирован | нет | события нет, локальный отказ |
| C | доступно | заблокирован | зависит от вашего рабочего решения | зафиксированный результат |
| D | заблокировано | заблокирован | нет | события нет, локальный отказ |
Слово «зависит» в строке C выбрано намеренно. Не прячьте решение о политике в столбце «пройдено/не пройдено». Укажите, разрешено ли одобренному процессу продолжать работу при заблокированном экране в вашей среде, и приведите ожидаемый результат в соответствие с этим решением.
Для HTTP проверяйте журналы приложения, а не только журналы доступа, если обратный прокси может отклонять или повторять запросы до того, как их увидит приложение. Для SSH проверяйте записи аутентификации и команд на сервере для изолированной учетной записи. Используйте новый идентификатор для каждой попытки. Повторное использование одной метки создает спор о задержанной доставке, когда нужен однозначный результат.
Запись аудита должна объяснять изменение состояния
Хороший журнал аудита позволяет проверяющему восстановить, кто запускал агента, какие действия он запрашивал и отклонил ли их шлюз или выполнил. Проверяющему не придется гадать, исчезло ли удаленное событие из-за блокировки хранилища, потери сети или того, что агент вообще не отправил запрос.
Приложение ведет журнал Sessions для запусков агентов и журнал Activity для отдельных вызовов. Оба журнала создаются из одного защищенного от записи зашифрованного аудита с хеш-цепочкой. Это два представления одной записи, а не конкурирующие журналы с разными версиями событий. Если тест обнаруживает расхождение между журналами, считайте это провалом теста, пока не сможете его объяснить.
После каждого тестового запуска сохраните в заметках следующие наблюдения:
- Идентификатор сессии, показанный при авторизации, и время ее одобрения или отклонения.
- Точное время изменения состояния хранилища и экрана.
- Результат, успех или отказ, для каждого запрошенного действия.
- Соответствующие записи Activity и Sessions.
- Доказательство от контролируемого ресурса, получил он действие или нет.
Затем проверьте цепочку офлайн:
sp audit verify
При успешной проверке должно появиться сообщение о том, что проверка пройдена, хотя точная формулировка может меняться от версии к версии. Важно, что проверка работает с шифротекстом и не требует открывать хранилище. Поэтому защищенный артефакт аудита можно передать проверяющему, которому нужно выявить подмену, не предоставляя ему учетные данные и возможность выполнять действия.
Не приписывайте этой команде лишнего. Корректная хеш-цепочка показывает, что записанная последовательность сохраняет целостность в рамках модели проверяющего. Она не доказывает, что вы выбрали правильный удаленный журнал, часы показывают точное время или тестовый ресурс не имел другого пути доступа. Сопоставляйте ее с удаленными свидетельствами.
Жизненный цикл процесса часто остается без проверки
Авторизация сессии должна завершаться после выхода процесса агента. Проверьте это явно: «я открыл новый терминал» не означает «предыдущий процесс завершился», а фоновый супервизор может сохранить дочерний процесс после исчезновения интерфейса.
Начните с чистого состояния. Завершите процесс агента, обычным для вас способом проверки процессов убедитесь, что он исчез, затем запустите другой процесс через тот же путь клиента. Его первый защищенный вызов должен создать новую сессию и запросить авторизацию. Если разрешение молча унаследовано, выясните, какой идентификатор его передал. Это может быть намеренной функцией, но тогда полномочия намного шире, чем подразумевает авторизация сессии.
Также проверьте неудачный запуск и скопированный клиент. Если процесс клиента запрашивает разрешение, завершается до вызова действия, а заменивший его процесс может использовать это разрешение, вы обнаружили ошибку жизненного цикла. Если процесс с другой подписью показывает то же понятное имя, интерфейс разрешения должен дать оператору достаточно информации о полномочиях, чтобы их различить.
Это не формальность. Инструменты для агентов быстро меняются: оболочки запускают помощников, транспорты переподключаются, а после сбоев выполняется восстановление. Авторизовать нужно тот объект, который выполняет защищенный вызов. Имя проекта или история чата не являются идентификатором выполнения.
Сон, перезапуск и потерю сети нужно проверять отдельно
Блокировку экрана часто проверяют на работающем ноутбуке, а затем предполагают, что результат распространяется на сон, перезагрузку и потерю сети. Это не так. Каждое событие меняет разные части системы.
При переходе в режим сна запишите, остается ли процесс агента активным, разрешает ли Mac используемый сетевой путь и меняется ли состояние хранилища. После перезапуска считайте каждый запуск агента новым и требуйте новую локальную разблокировку перед защищенным использованием. При потере сети проверьте, что неудачный вызов не приводит к небезопасной повторной попытке после блокировки хранилища или завершения исходного процесса.
Проводите эти эксперименты небольшими. Полезный тест повторной попытки использует один идентификатор запроса и принимающую сторону, способную показать, получила она ноль, один или несколько запросов. Начните запрос, в контролируемый момент отключите сетевой путь, заблокируйте хранилище, восстановите сетевой путь и проверьте, не произошла ли отложенная доставка. Если запрос меняет состояние, используйте одноразовый ресурс. Повторная попытка обычного чтения отличается от повторной попытки операции, меняющей состояние.
Не превращайте это в общий движок политик внутри документа с тестами. Вопрос уже: выдает ли фиксированная последовательность решений ожидаемый отказ, когда обычные события компьютера прерывают работу агента? Ясные доказательства полезнее огромной таблицы вымышленных правил.
В завершенном плане должно остаться одно однозначное утверждение
Готовый план должен позволять утверждать на основании доказательств, что заблокированный экран macOS и заблокированное хранилище проверялись независимо. Он также должен показать, мог ли одобренный процесс действовать без присмотра, блокировало ли подтверждение каждого вызова второе использование и остался ли отклоненный вызов за пределами удаленной системы.
Сформулируйте итоговый вывод простыми словами: «Когда хранилище было заблокировано, агент не мог использовать настроенные HTTP- или SSH-учетные данные, независимо от того, был экран macOS заблокирован или разблокирован». Приложите запись с контролируемого ресурса и результат проверки аудита. Затем отдельно укажите рабочее решение о том, что одобренному агенту разрешено делать, когда заблокирован только экран.
Последнее предложение предотвращает обычную путаницу при разборе инцидента. С вашей политикой работы без присмотра можно не соглашаться. Но ее не должны принимать за доказательство того, что шлюз хранилища действительно сработал.
Вопросы и ответы
Блокирует ли заблокированный Mac учетные данные AI-агента?
Нет. Блокировка экрана защищает интерактивную сессию macOS от человека за клавиатурой. Блокировка хранилища запрещает защищенные действия даже уже запущенному процессу агента, поэтому эти состояния нужно тестировать отдельно.
Что происходит с одобренной сессией агента после блокировки хранилища?
Не должно. Заблокируйте хранилище, пока процесс агента продолжает работать, затем повторите разрешенный вызов. Вызов должен быть отклонен, потому что шлюз хранилища закрыт, даже если процесс уже получил разрешение на сессию.
Потребуется ли агенту новое разрешение после разблокировки хранилища?
После нового открытия хранилища новый процесс должен получить собственное разрешение на сессию. Разрешение относится к этому запуску, а не к расплывчатому идентификатору вроде окна терминала, папки проекта или сохраненного имени агента.
Когда нужно требовать подтверждение каждого использования учетных данных?
Ключ с подтверждением каждого вызова запрашивает разрешение при каждом использовании учетных данных, в том числе у процесса, уже имеющего разрешение на сессию. Такой режим нужен для действий, требующих отдельного решения человека, а не для исправления неисправного шлюза сессии.
Нужно ли тестировать блокировку экрана и блокировку хранилища отдельно?
Нужно выполнить оба теста и зафиксировать разницу. Сначала проверьте блокировку хранилища приложения, пока компьютер остается активным, затем проверьте экран блокировки macOS, пока приложение находится в своем фактическом доступном состоянии. Иначе один результат может скрыть другой.
Что должно быть указано в запросе разрешения для сессии?
Первый защищенный вызов нового процесса агента должен показать карточку разрешения, где процесс идентифицирован полномочиями подписи кода. Если в карточке есть только понятное имя процесса, принять обоснованное решение будет невозможно.
Как убедиться, что отклоненный вызов агента все же не дошел до API или SSH-хоста?
Считайте отказ корректным только тогда, когда действие действительно не покинуло компьютер. Проверьте полученную ошибку, журнал Activity и цепочку аудита, затем убедитесь на удаленной стороне, что она не получила запрос или команду.
Чем отличается заблокированный экран от заблокированного хранилища?
Блокировка экрана ограничивает пользовательский интерфейс. Шлюз хранилища ограничивает действия: пока он заблокирован, любой защищенный вызов HTTP или SSH должен быть отклонен, даже если агент продолжает локально выполнять код.
Зачем проверять новый процесс агента после выдачи разрешения?
Повторите тест с новым процессом агента. Разрешение старой сессии не должно незаметно переноситься, поскольку новый процесс имеет другой жизненный цикл и может быть подписан другим ключом.
Можно ли проверить аудит без открытия хранилища?
Запустите sp audit verify для экспортированных или доступных данных аудита в соответствии с рабочим процессом вашей установки. Успешная проверка подтверждает внутреннюю согласованность зашифрованной хеш-цепочки, но не доказывает разумность ваших тестовых утверждений. Зафиксируйте наблюдаемые результаты вместе с тестом.