Читать 7 мин

Привязка запроса к одобрению предотвращает изменения после нажатия

Привязка запроса к одобрению не позволяет ИИ-клиенту изменить HTTP-запрос или SSH-команду после того, как человек одобрил действие.

Привязка запроса к одобрению предотвращает изменения после нажатия

Одобрение человеком имеет смысл только тогда, когда оно разрешает действие, которое уже нельзя изменить. Если показать предложенный агентом HTTP-запрос или SSH-команду, а затем позволить тому же агенту позже передать окончательные параметры, между проверкой и использованием остаётся достаточно большой промежуток, чтобы провести через него разрушительный запрос.

Я видел, как эта ошибка приходит в успокаивающем виде: аккуратный лист одобрения, бейдж с идентификатором процесса, зелёный статус подтверждения. Затем реализация отправляет токен одобрения, хранящийся у клиента, обратно по протоколу и принимает рядом новый URL или команду. Человек одобрил одно действие. Исполнитель выполнил другое. Это неудачная схема авторизации, даже если никто не собирался её обходить.

Предпросмотр должен описывать неизменяемый объект авторизации

Экран одобрения должен отображать сохранённый объект действия, а исполнитель после одобрения должен отправлять именно этот объект. Экран показывает авторитетное состояние, а не просит клиента ещё раз аккуратнее повторить своё предложение.

Создайте объект до появления любого запроса на одобрение. Присвойте ему случайный идентификатор действия, свяжите его с запрашивающим процессом и сессией, разрешите входные данные для конкретного канала и сохраните объект в памяти или в зашифрованном локальном хранилище под контролем исполнителя. Клиент может получить статус ожидания и идентификатор. Он не должен получать полномочие, позволяющее позже прикрепить новые параметры выполнения.

Полезно думать о таком объекте как о кухонном заказе, а не как о разрешительной записке. После того как официант отметил заказ одобренным, кухня не просит клиента заново описывать ужин. Она готовит то, что указано в имеющемся заказе. Если заказ меняется, кухня получает новый талон, а клиент видит это изменение.

Неизменяемый объект должен включать больше полей, чем видно в компактном предпросмотре. В нём также нужны идентификатор процесса, идентификатор сессии, время создания, срок действия, канал, ссылка на учётные данные, нормализованные параметры действия и связывающий дайджест. Дайджест помогает обнаружить случайное изменение или намеренную подмену, но настоящую работу по защите выполняет исполнитель, владеющий объектом.

Ответ на одобрение должен означать только следующее: «одобрить действие 7c91... со связывающим дайджестом sha256:...». Он не должен означать «этому процессу разрешено выполнить HTTP-вызов» или «вызывающая сторона может позже выполнить команду X». Такие широкие формулировки уместны при авторизации сессии, но они не заменяют согласие на конкретный побочный эффект.

Это особенно важно для автономных агентов, потому что клиент не является надёжным помощником, который безошибочно переписывает решение человека. Это активная программа, способная повторить запрос, составить последующие вызовы, изменить план после результата инструмента или просто содержать ошибку. Считайте подозрительным любое поле, на которое клиент всё ещё может влиять после предпросмотра.

HTTP-предпросмотр должен называть все фактические параметры

Одобрение HTTP-запроса должно привязывать метод, полный адрес назначения, фактические заголовки, тело и параметры отправки, способные изменить смысл запроса. Предпросмотр «POST в платёжный сервис» даёт человеку слишком мало информации для одобрения вызова, который меняет состояние.

RFC 9110 разделяет метод запроса, цель, поля и содержимое, потому что сервер может придавать каждому из них разный смысл. Код авторизации должен сохранять это разделение. Не составляйте для листа одобрения одну удобную фразу, а затем не позволяйте нижнему уровню заполнять неудобные детали.

Для исходящего запроса зафиксируйте эти значения после разрешения шаблонов и значений по умолчанию:

  • Схему, имя хоста, порт, путь и строку запроса.
  • HTTP-метод и возможность следовать перенаправлениям.
  • Все фактические имена и значения заголовков, кроме секретных данных, которые добавляет хранилище.
  • Итоговые байты тела, его тип содержимого, длину и дайджест.
  • Ссылку на учётные данные и режим их добавления, например bearer или пользовательский заголовок.

Значение учётных данных не должно попадать ни в предпросмотр, ни в контекст агента. Но человеку нужна достаточная информация, чтобы оценить их использование. Фраза «учётные данные для продуктивных платежей отправляются только на api.example.test как bearer-токен» описывает ситуацию совсем иначе, чем «учётные данные добавлены». Исполнитель может вывести это описание из записи хранилища, не раскрывая токен.

Не одобряйте нераскрытый шаблон. Допустим, агент предлагает POST /users/{id}/role с телом, содержащим {role}. Если другой компонент раскроет эти переменные после одобрения, он сможет изменить фактическую цель или уровень полномочий. Сначала разрешите переменные, затем создайте объект действия. Если входные данные намеренно станут доступны только позже, запросите одобрение в момент, когда они станут конкретными.

Заголовки требуют большей заботы, чем обычно им уделяют команды. Дублирующийся заголовок, изменённый Content-Type, добавленный заголовок переопределения или другая кодировка параметров запроса могут изменить поведение сервера, хотя дружелюбное резюме останется прежним. Сохраняйте повторяющиеся поля в исходном порядке, если протокол или целевой сервер придаёт порядку значение. Отклоняйте неоднозначные входные данные, а не объединяйте их молча через запятые.

Разумная внутренняя структура данных может выглядеть так. Это шаблон реализации, а не контракт конечной точки:

{
  "action_id": "7c91e2d4",
  "binding": "sha256:4f06...",
  "caller": {"session": "p-481", "process_start": "..."},
  "http": {
    "method": "PATCH",
    "url": "https://api.example.test/v1/users/42",
    "headers": [["content-type", "application/json"]],
    "body_sha256": "a4d8...",
    "body_length": 31,
    "redirects": "deny"
  },
  "credential_ref": "vault:payments-prod"
}

После того как человек одобрил этот объект, транспортный уровень читает http и credential_ref из собственной сохранённой записи. Он не принимает от клиента второй URL, карту заголовков или тело. Именно это последнее правило предотвращает ошибку, а дайджест лишь доказывает, к какой записи относилось одобрение.

SSH-командам нужен разрешённый контекст выполнения

Предпросмотр SSH-команды должен привязывать удалённый контекст выполнения, потому что сама строка команды не сообщает человеку, что именно произойдёт. Один и тот же текст может иметь разный эффект при другом пользователе, хосте, shell, рабочем каталоге, окружении или потоке stdin.

RFC 4254 определяет запрос протокола SSH для выполнения команды, но не создаёт понятной человеку границы одобрения. SSH передаёт серверу строку команды. Удалённая интерпретация shell, настройки учётной записи, принудительные команды и оболочки-обёртки могут добавить смысл, которого нет в простом предпросмотре.

Сохраните и покажите имя хоста, порт, удалённого пользователя, ожидаемый способ проверки хоста, ссылку на идентификатор, точные байты команды, режим выполнения, выделение терминала, рабочий каталог, переданное окружение, а также дайджест и длину stdin. Для файловой операции через SSH-помощник также привяжите удалённый путь, тип операции, дайджест файла и поведение при перезаписи.

Режим выполнения не является косметической деталью. Эти варианты не взаимозаменяемы:

/usr/local/bin/deploy --environment=staging
sh -lc '/usr/local/bin/deploy --environment=staging'

В первом случае запрашивается прямое выполнение, если помощник его поддерживает. Во втором явно запрашивается, чтобы shell разобрал строку. Разбор shell добавляет раскрытие переменных, подстановку команд, поведение при запуске shell и правила кавычек. Если продукт поддерживает оба режима, обозначайте их понятными словами и никогда не переводите один в другой после одобрения.

Не создавайте предпросмотр из команды, отформатированной для показа, а затем не выполняйте отдельно собранный массив аргументов. Строка для отображения может скрыть пустой аргумент, перевод строки, непечатаемый символ или разницу между --file=/tmp/a b и двумя аргументами. Формируйте безопасное экранированное представление из той же последовательности байтов или вектора аргументов, который использует помощник. Если команда содержит байты, которые нельзя безопасно показать, отклоните её либо покажите явное закодированное представление, доступное для проверки пользователем.

Изменения удалённого назначения требуют такой же дисциплины, как HTTP-перенаправления. Локальный псевдоним в конфигурации SSH, промежуточный прокси или поиск параметров хоста могут превратить короткое имя хоста в другое место назначения. До одобрения разрешите итоговый план соединения и привяжите его. В системах, где DNS-перепривязка входит в модель угроз, осторожно добавьте отдельную политику адресов хоста. Фиксация адреса может нарушить обычное резервирование, а игнорирование враждебного резолвера может отправить корректное имя хоста не на ту машину. Не делайте вид, будто предпросмотр команды решает эту отдельную проблему.

Уязвимый промежуток начинается после нажатия человеком кнопки

Ошибка возникает, когда интерфейс проверяет предложенные параметры, записывает ответ «да», а последующий путь выполнения читает изменяемые параметры из клиента. Часто она скрывается за обычным асинхронным кодом.

Рассмотрим процесс агента, который просит шлюз перевести деньги:

  1. Клиент отправляет POST https://api.example.test/transfers с телом на 50 единиц.
  2. Шлюз создаёт предпросмотр и ждёт одобрения человека.
  3. Человек одобряет действие после проверки назначения и суммы.
  4. Клиент отправляет execute с идентификатором одобрения и новым телом на 5 000 единиц.
  5. Шлюз проверяет только действительность идентификатора одобрения, добавляет учётные данные и отправляет новое тело.

Для этой последовательности не нужны ни взломанный интерфейс, ни украденные учётные данные. Клиент использовал API, который предоставил шлюз. Тест, который одобряет исходный запрос и проверяет только работоспособность идентификатора, пройдёт. Тест, сравнивающий итоговые исходящие байты с байтами, представленными одобренным объектом, завершится ошибкой, и именно этого вы хотите.

Та же проблема возникает, когда шлюз хранит изменяемый объект запроса по ссылке. Воркер предпросмотра читает его, обработчик повторных попыток на стороне агента меняет его, а воркер отправки позже передаёт уже изменённую версию. Простого копирования объекта недостаточно, если вложенные карты, буферы тела или обратные вызовы всё ещё общие. Создайте неизменяемое значение без ссылок, принадлежащих клиенту, либо сериализуйте его в авторитетное представление и восстанавливайте только из этого представления.

Срок действия не исправляет изменяемое состояние. Одобрение, действующее тридцать секунд, всё ещё может разрешить изменённый запрос, отправленный на первой секунде. Ограничения частоты тоже не исправляют проблему. Они уменьшают частоту эксплуатации ошибки клиентом, но не отвечают на вопрос, одобрил ли человек именно этот эффект.

Сохраняйте конечный автомат достаточно маленьким, чтобы его можно было проверять:

proposed -\u003e frozen -\u003e awaiting_human -\u003e approved -\u003e dispatched
                         |                 |
                         v                 v
                      rejected           expired

Только переход от approved к dispatched может выполнять внешнее действие. Этот переход должен загрузить замороженную запись по идентификатору действия, повторно проверить вызывающую сторону и срок действия, а затем напрямую передать запись исполнителю HTTP или SSH. Любой запрос изменить параметры возвращается в состояние proposed и создаёт новый идентификатор.

Привязывайте байты там, где смысл может измениться

Храните учётные данные запросов вне агентов
Sallyport сам выполняет HTTP-запросы, поэтому API-учётные данные не проходят через агента.

Для привязки нужно стабильное представление, иначе два компонента могут считать, что одобрили один и тот же запрос, а в проводе создать разные данные. Сложность в том, чтобы определить, какое представление считать авторитетным.

Для простых JSON-запросов нормализуйте структурированную форму по документированным правилам, сериализуйте её один раз и сохраните итоговые байты тела и дайджест. Предпросмотр может показывать понятный JSON, а путь отправки должен передавать сохранённые байты. После одобрения нельзя разбирать, форматировать и сериализовать тело заново, если преобразованный результат не был одобренным объектом.

Для форм, multipart-загрузок, повторяющихся заголовков или произвольных двоичных данных границей безопасности обычно лучше сделать байты. Привязывайте точные байты, тип содержимого и решения о фрейминге передачи, которые влияют на интерпретацию сервером. Дайджест позволяет интерфейсу обозначить большой объём данных, не помещая личный документ в лист одобрения, но исполнитель должен хранить эти точные байты или заново получить их из доверенного состояния.

Канонизация URL - ещё одна ловушка. Нормализация регистра имени хоста обычно безопасна. Декодирование и повторное кодирование пути, сортировка пар запроса, удаление пустого значения или признание + и %20 одинаковыми могут изменить маршрутизацию или проверку запроса приложением. Выберите узко определённую каноническую форму, опишите её и отклоняйте ввод, допускающий несколько правдоподобных интерпретаций. Фраза «мы нормализуем URL» сама по себе не является свойством безопасности.

Для SSH вектор аргументов лучше строки shell, если помощник протокола может выполнить его без запуска shell. Привязывайте каждый аргумент как отдельную последовательность байтов. Если удалённая сторона неизбежно получает одну строку shell-команды, привязывайте эту строку без изменений и честно показывайте её экранирование. Не утверждайте, что анализатор на локальной машине способен доказать, что сделает произвольный файл запуска удалённого shell.

Дайджест одобрения должен охватывать версионированное представление с разделением доменов. Добавьте к закодированным данным фиксированную метку вроде action-v1/http или action-v1/ssh, включите все неизменяемые поля с однозначными длинами или детерминированным сериализатором, а затем вычислите хеш. Версионирование не позволит старой интерпретации незаметно превратиться в новую после обновления. Разделение доменов не даст HTTP-объекту совпасть с SSH-объектом только потому, что их сериализованные байты случайно совпали.

Идентичность вызывающей стороны и привязка действия решают разные задачи

Авторизация на уровне сессии показывает, какой запущенный процесс может запрашивать действия. Привязка действия показывает, какое именно действие этот процесс может выполнить. Нужны обе проверки, и одна не заменяет другую.

Привязывайте действие к идентичности процесса, которую шлюз наблюдает сам, а не к имени, присланному клиентом. В macOS это может включать полномочие подписи кода процесса, идентификатор процесса и момент запуска конкретного экземпляра. Момент запуска важен, потому что операционная система может повторно использовать идентификатор процесса. Если процесс завершился, удалите его ожидающие и одобренные действия вместе с полномочиями сессии.

Не позволяйте дочернему процессу наследовать широкое одобрение только потому, что он знает идентификатор родителя. Наблюдайте каждый подключающийся процесс на границе шлюза. Если архитектура инструментов делает это невозможным, прямо укажите ограничение и сократите срок действия одобрения, а не создавайте ложную уверенность.

Одобрение человека тоже должно иметь короткий ограниченный срок. Срок действия должен находиться в замороженном объекте и решении об одобрении, а не только в таймере интерфейса. После истечения срока исполнитель отклоняет отправку, даже если клиент всё это время хранил старый ответ. Отозванная сессия также должна запрещать отправку любых одобренных, но ещё не использованных действий.

Авторизация Sallyport на уровне сессии может установить, имеет ли вновь подключившийся процесс агента право вообще использовать запуск, но шлюзу действий всё равно нужна отдельная неизменяемая граница для каждого предпросмотренного побочного эффекта. Решение для сессии намеренно широкое, а одобрение HTTP-запроса или SSH-команды должно оставаться точным.

Не используйте идентичность процесса как причину показывать меньше деталей. Даже доверенный подписанный код может содержать ошибки, получать неожиданные инструкции через внедрение в запросы или включать плагин, который пошёл не по тому пути, который ожидал автор. Ценность человеческого контроля в том, что он позволяет увидеть конкретный эффект до того, как тот покинет машину.

Повторы и перенаправления должны оставаться внутри одобренной границы

Проверяйте цепочку аудита
Проверяйте зашифрованную хеш-цепочку офлайн с помощью sp audit verify, не открывая хранилище.

Транспортный повтор может использовать то же одобрение только тогда, когда он повторно отправляет то же замороженное действие в записанных условиях. Многие реализации повторов незаметно нарушают это правило, заново собирая запросы из изменяемого состояния клиента.

Определите допустимое поведение при повторе в момент заморозки действия. Например, разрешите одну повторную отправку после сбоя соединения, если до этого не пришёл HTTP-ответ, с тем же URL, заголовками, байтами тела и ссылкой на учётные данные. Записывайте каждую попытку под тем же идентификатором действия. Не повторяйте неидемпотентный запрос после неопределённого ответа, если протокол и целевой API не предоставляют надёжный механизм идемпотентности.

Токен идемпотентности полезен только тогда, когда он тоже привязан. Если его создаёт исполнитель, создайте его при заморозке действия и сохраните в наборе одобренных заголовков. Если его передаёт клиент, считайте его частью одобренного запроса. Замена токена при повторе может превратить одно одобрение во второй побочный эффект.

Восстановление аутентификации требует такой же осторожности. Если хранилище внутренне обновляет учётные данные, но отправляет тот же одобренный запрос тому же назначению, действие может оставаться в допустимой границе. Если восстановление меняет арендатора, назначение, область действия или заголовки, видимые приложению, это уже другой запрос, которому нужно новое одобрение. Не допускайте фонового механизма, превращающего отказ в авторизации в непроверенный альтернативный вызов.

Поведение HTTP по умолчанию для одобренных действий должно запрещать перенаправления. Даже перенаправление, сохраняющее все важные поля, может перейти к другому центру полномочий. Если продукт поддерживает переход по перенаправлениям, проверяйте каждый шаг до отправки и требуйте новый объект действия, когда меняются хост, порт, метод или тело. Относительное перенаправление в пределах того же центра полномочий обрабатывайте по явно заданному правилу, а не по случайному поведению используемой библиотеки клиента.

Повторное подключение SSH подчиняется похожему правилу. Подключайтесь снова только к привязанному плану хоста с привязанным идентификатором и командой. Новый отпечаток хоста, изменившийся маршрут через прокси или другой результат разрешения имени хоста могут потребовать нового решения человека, в зависимости от вашей модели угроз. Код повторных подключений должен быть настолько простым, чтобы аудитор мог увидеть: он не способен расширить исходное одобрение.

Аудитируйте одобрение и выполнение как отдельные события

Запись аудита должна сохранять и действие, которое проверил человек, и попытки, предпринятые исполнителем. Журнал, где записан только итоговый запрос, не доказывает, что он совпадал с предпросмотром, а журнал только с одобрением не доказывает, что отправка состоялась.

Запишите идентификатор замороженного действия, связывающий дайджест, идентичность вызывающей стороны, безопасные для предпросмотра поля, идентификатор ссылки на учётные данные, время одобрения, срок действия и результат. Затем запишите каждую попытку отправки с тем же идентификатором, результатом транспорта, причиной повтора, если он был, и дайджестом фактически отправленного тела или команды. Не помещайте секретные значения ни в журнал для пользователя, ни в ответ агента.

Здесь хешированная цепочка журнала особенно полезна. Цепочка может обнаружить удаление или перестановку предыдущих записей, если проверка охватывает сохранённую последовательность. Но она не сделает расплывчатое событие полезным. Если запись говорит только «одобрено действие SSH», цепочка навсегда сохранит именно эту расплывчатую формулировку.

Для шлюза, который ведёт зашифрованный журнал с хеш-цепочкой и недоступной для записи историей, офлайн-проверка должна независимо проверять цепочку шифротекста, не обращаясь к хранилищу. Sallyport предоставляет такую проверку через sp audit verify, поэтому следователь может проверить непрерывность журнала, не открывая хранилище учётных данных.

Вывод аудита должен делать привязку видимой. Проверяющий должен видеть, что одобрение 7c91e2d4 охватывало дайджест 4f06..., что отправка использовала тот же дайджест, а исполнитель отклонил любое несовпадающее предложение. Избегайте журналов, где во время одобрения печатается человеческое резюме, а во время выполнения выводится отдельный необработанный запрос без устойчивой связи между ними.

Тестируйте клиента так, будто он хочет передумать

Храните SSH-ключи локально
Направляйте SSH через sp-ssh, пока SSH-идентификатор остаётся зашифрованным внутри приложения.

Обычный интеграционный тест доказывает, что одобренное действие выполняется успешно. Тест безопасности должен доказать, что одобренное действие не может превратиться в другое, даже если после нажатия человеком кнопки клиент ведёт себя плохо.

Создайте тестовый стенд, который приостанавливает выполнение сразу после одобрения. Пока отправка ждёт, по очереди меняйте каждое поле под управлением клиента: метод, хост, порт, путь, запрос, значения заголовков, повторяющиеся заголовки, тело, выбор учётных данных, настройку перенаправления, пользователя SSH, команду, окружение, stdin и дайджест файла. Исполнитель должен либо отправить исходное сохранённое действие, либо отклонить попытку. Он никогда не должен отправлять изменённую версию.

Проверяйте состояния гонки так же целенаправленно, как изменения отдельных полей. Отправьте два сообщения execute для одного одобренного идентификатора. Одновременно отмените одобрение и отправьте execute. Завершите запрашивающий процесс, затем подключите новый процесс, который попробует старый идентификатор. Перезапустите интерфейс, пока одобрение ожидает решения. Заполните хранилище ожидающих действий до запуска очистки по истечении срока. Это обычные события жизненного цикла, и код авторизации часто ломается именно на границах между ними.

Используйте тестовый HTTP-сервер, который сообщает точный метод, цель, повторяющиеся заголовки и дайджест полученного тела. Используйте контролируемую SSH-конечную точку, записывающую удалённого пользователя, байты команды, запрос терминала, окружение и дайджест stdin. Проверяйте эти наблюдения, а не только объект намерения шлюза. Смысл теста в том, чтобы поймать расхождение между намерением и транспортом.

Наконец, сделайте ошибки тестов понятными. Полезное сообщение говорит, что дайджест одобрения 4f06... охватывал PATCH /v1/users/42, а при попытке отправки был передан другой дайджест и запрос отклонён. Расплывчатое сообщение «ошибка авторизации» отправляет инженеров искать проблему в отладочных выводах и подталкивает их ослабить проверки, пока тест не станет зелёным.

Размещайте границу неизменяемости рядом с исполнителем

Компонент, который владеет учётными данными и открывает HTTP- или SSH-соединение, должен владеть замороженным одобренным действием. Если граница находится раньше, другой слой сможет переосмыслить, заново собрать или заменить его.

Такая конструкция также сохраняет честность взаимодействия с человеком. Человек видит предпросмотр, созданный из объекта, который будет отправлен; агент получает результаты, а не учётные данные; журнал аудита содержит один идентификатор, связывающий намерение, одобрение и выполнение. Это разные преимущества, но все они зависят от одного отказа принимать изменения после нажатия кнопки.

Если ваш текущий процесс возвращает агенту токен одобрения, а затем принимает новые поля действия, исправьте это прежде, чем улучшать формулировки, добавлять дополнительные политики или показывать ещё один диалог одобрения. Сначала заморозьте запрос. Затем заставьте исполнителя доказать, что он использовал замороженную запись.

Вопросы и ответы

Что такое привязка запроса к одобрению?

Предпросмотр заслуживает доверия только тогда, когда исполнитель сохраняет точное одобренное действие и отклоняет любую последующую замену, присланную клиентом. Если одобрение лишь возвращает клиенту многоразовое «да», такой предпросмотр становится декоративным.

Предотвращает ли одобрение сессии изменения запроса после одобрения?

Нет. Процесс с действующей сессией всё равно может отправить другой запрос после того, как человек прочитал предпросмотр. Одобрение сессии отвечает на вопрос, кто может запрашивать действия, а привязка запроса определяет, какое именно действие этот процесс может выполнить.

Какие поля HTTP-запроса нужно привязать к одобрению?

Укажите метод, полный адрес назначения, заголовки после добавления учётных данных, байты тела или его дайджест, поведение при перенаправлениях и ссылку на учётные данные. Секреты показывать не нужно, но следует указать, какие учётные данные используются и куда они будут переданы.

Что должен включать предпросмотр SSH-одобрения?

Как минимум привяжите хост, порт, удалённого пользователя, идентификатор аутентификации, режим выполнения, точные байты команды, окружение, рабочий каталог, выделение терминала и stdin или передаваемые данные. Метки вроде «развёртывание» недостаточно.

Безопасны ли HTTP-перенаправления после одобрения действия?

Считайте перенаправление новым исходящим запросом, если оно меняет хост, метод или тело. Тихое следование перенаправлению позволяет серверу выбрать действие, которое человек не проверял.

Можно ли безопасно повторить одобренный запрос?

Повторная попытка может использовать то же одобрение только тогда, когда она повторно отправляет неизменяемое действие в рамках узкого, заранее записанного правила. Если при повторе меняются тело, адрес назначения, учётные данные или поведение идемпотентности, нужно новое решение.

Должен ли клиент получать токен одобрения?

Обычно нет. Токен одобрения, который хранится у клиента, можно скопировать, воспроизвести или сопоставить с изменёнными параметрами, если исполнитель независимо не сравнивает его с неизменяемым состоянием. Авторитетный объект действия должен оставаться внутри процесса, который выполняет сетевой или SSH-вызов.

Хешировать исходные байты HTTP или канонические поля?

Используйте каноническое представление полей, если семантическую эквивалентность можно точно определить, а там, где это невозможно, сохраняйте дайджест итогового тела в проводном формате. Особенно строго обрабатывайте повторяющиеся заголовки, кодирование параметров запроса, multipart-тела и строки shell-команд.

Что должны содержать журналы аудита одобренных действий?

Записи об одобрении показывают, что именно человеку предложили разрешить. Записи о выполнении показывают, что исполнитель предпринял и чем всё закончилось, включая повторы и ошибки. Если хранить оба типа записей, расследования становятся гораздо менее предположительными.

Как проверить ошибки проверки и использования во время одобрения?

Создайте атакующие тесты: одобрите одно действие, а затем до выполнения измените каждое поле, которым управляет клиент. Проверьте перенаправления, повторяющиеся заголовки, обработку shell-команд, замену процесса, повторное воспроизведение, истечение срока и прерванный процесс одобрения.

Sallyport

Sallyport выполняет API-вызовы и SSH-команды за вашего ИИ-агента. Ключи остаются в локальном хранилище на вашем Mac; вы подтверждаете каждый запуск, и каждое действие попадает в запечатанный журнал.

© 2026 Sallyport · Открытый код по лицензии Apache-2.0 · Oleg Sotnikov