Основная идея
Инфраструктурному агенту недостаточно запретить изменения и попросить не показывать пароли. Чувствительные данные нужно отфильтровать до того, как результат инструмента попадёт в контекст модели.
Представим запрос: «Проверь состояние контейнера перед обновлением». Агент обращается к инфраструктурному API, получает ответ и сообщает, что приложение работает, а нужное количество реплик запущено. Никаких изменений не произошло, пароль в ответе пользователю не появился. Кажется, всё безопасно.
Но ответ API может содержать не только статус: вместе с ним приходят переменные окружения, строки подключения, параметры конфигурации или учётные данные интеграций. Если инструмент передал весь объект языковой модели, секрет уже пересёк границу, которую следовало защищать. Удалить его из итогового сообщения — слишком поздно.
Секрет может попасть в контекст без утечки в ответе
В обычном приложении разработчик выбирает, какие поля вернуть вызывающему коду. У агента между внешним сервисом и решением появляется ещё один получатель — модель. Поэтому необходимо отдельно определить, что инструмент вправе прочитать и что он вправе показать модели.
Риск не ограничен очевидным полем с названием password. Токен может оказаться в произвольной переменной окружения, адресе репозитория, аргументах запуска, ответе об ошибке или строке лога. Попытка замаскировать несколько известных ключей не покрывает остальные варианты.
Именно поэтому при проектировании инфраструктурного помощника для Dockhost важным требованием стала не маскировка финального ответа, а ограничение самого результата чтения. Модель не должна получать лишние данные только потому, что API умеет их возвращать.
Нужна сводка, а не весь ответ API
Для вопроса о готовности контейнера достаточно небольшого набора фактов: его состояние, число реплик, некоторые числовые лимиты и наличие необходимых привязок. Значения переменных окружения для такой проверки не нужны.
Безопаснее обработать исходный ответ внутри отдельного процесса и вывести наружу только заранее разрешённые поля. Например, вместо полного списка переменных — количество записей; вместо произвольного текста ошибки — известный код; вместо неожиданного статуса — отметку «неизвестно».
Такой подход называют фильтрацией по белому списку. Он предсказуемее, чем поиск слов «ключ» и «пароль»: неизвестное поле по умолчанию не проходит. Важно также не печатать сырые HTTP-ответы, адреса с учётными данными и тексты исключений — ошибка сама может содержать секрет.
Права доступа решают другую задачу
Режим только для чтения полезен: он уменьшает риск случайно удалить контейнер или изменить настройки. Но он не определяет, какие значения вернут методы чтения. Агент без права записи всё ещё может получить конфиденциальную конфигурацию.
Это две независимые защиты. Права ограничивают доступные действия и ресурсы, а фильтр ограничивает данные, проходящие к модели. Если доступ распространяется на несколько проектов, одних ограничений набора команд может быть недостаточно для разграничения проектов.
Поэтому для подключения нужны и минимальные полномочия, и контролируемый канал чтения. Прямой вызов инструмента, который возвращает секреты в собственном результате, нельзя сделать безопасным последующей правкой ответа ассистента.
Очищённый ответ нельзя использовать для обновления
Есть обратная ловушка. Сводка без секретов годится для диагностики, но не для полной замены конфигурации. Если взять её как основу запроса на обновление, можно случайно удалить переменные, порты или подключённые диски, которых в сводке просто нет.
Для изменения одного параметра лучше использовать узкую операцию, затрагивающую только этот параметр. Если сервис требует отправить полную конфигурацию, безопасный исполнитель должен получить её внутри защищённого процесса, сохранить неизменяемые поля, внести разрешённую правку и показать агенту только очищенное описание результата.
Так разделяются два разных объекта: полные данные для корректной операции и минимальные данные для принятия решения моделью. Подменять один другим нельзя.
Что можно проверить на практике
Для такого подхода полезны тесты с искусственными секретами: подставить значения в разные поля API, имитировать ошибки, некорректные ответы и перенаправления, затем проверить вывод процесса. В реализованном варианте подобные проверки проводились для чтения инфраструктурных данных и обработки ошибок.
Но успешные тесты отдельного обработчика не означают, что полностью защищены внешний MCP-сервер, другие инструменты агента и вся цепочка логирования. Они подтверждают только проверенные пути. Реальные операции с аккаунтом и независимое сравнение качества работы агента с этим навыком не проводились.
Граница безопасности — перед моделью
Обычная рекомендация «не выводить секреты пользователю» описывает слишком позднюю точку контроля. При работе агента с инфраструктурой критический момент наступает раньше — когда внешний ответ превращается в часть контекста модели.
Модель должна видеть не всё, что способен прочитать её инструмент, а только то, что необходимо для следующего решения.
Из этого следует практическое правило: сначала ограничивать права, затем пропускать каждый чувствительный ответ через узкую проверяемую проекцию и отдельно сохранять полный контекст только внутри защищённого исполнителя, когда он действительно нужен для изменения. Такая архитектура уменьшает поверхность раскрытия данных, не жертвуя корректностью операций.
