Покрытие и ограничения¶
Эта страница честно описывает, что Agate инспектирует сегодня, а что
пересылает без инспекции — чтобы вы разворачивали его, не переоценивая защиту.
Модель угроз описывает целевую модель безопасности; эта
страница — честное текущее состояние. Полный анализ и дорожная карта по
закрытию пробелов находятся в репозитории:
docs/design/security-coverage-roadmap.md.
Прочитайте это, прежде чем полагаться на Agate как на единственный барьер
Сейчас Agate обеспечивает авторизацию вызовов инструментов (по имени и по правилам запрета аргументов), редакцию секретов в исходящем тексте, результатах инструментов и состоянии, SSRF-скрин на обеих «ногах», валидацию/ограничение RFC 6902-патчей, fail-closed для битых событий, а также опциональную память реплея между прогонами. Это всё ещё один из слоёв защиты, а не полный «межсетевой экран» (не моделируется семантика состояния) — см. дорожную карту.
Что инспектируется¶
| Событие / ввод | Что происходит | Может ли политика вмешаться? |
|---|---|---|
TOOL_CALL_* (собранный) |
буферизуется по id вызова в полный вызов инструмента, затем оценивается; аргументы проверяются на SSRF-URL. Удержанные START/ARGS пересылаются только если вызов разрешён, поэтому конкурентные или незакрытые (без TOOL_CALL_END) вызовы не утекут фреймами запрещённого вызова; незакрытый вызов всё равно оценивается в конце прогона |
Да — разрешить/запретить по имени и по правилам запрета аргументов ([[policy.tools.deny_arguments]]); SSRF-URL в аргументах отбрасывает вызов |
TEXT_MESSAGE_CONTENT / TEXT_MESSAGE_CHUNK |
текст ассистента сканируется на шаблоны секретов и SSRF-URL (обе формы — с конвертом и самодостаточная) | Да — редактировать (литерал или regex); SSRF-URL отбрасывает фрагмент |
TOOL_CALL_RESULT |
содержимое результата сканируется на шаблоны секретов и SSRF-URL | Да — редактировать (литерал или regex; поверхность косвенной инъекции / эксфильтрации); SSRF-URL отбрасывает результат |
STATE_SNAPSHOT / STATE_DELTA |
бюджет размера; STATE_DELTA валидируется как корректный RFC 6902-патч и ограничивается (число операций, глубина указателя, размер value на операцию); payload сканируется на маркеры секретов |
Да — битый патч fail-closed, превышение бюджета отклоняется, маркер секрета запрещается (структурный payload нельзя замаскировать) |
Жизненный цикл (RUN_*, STEP_*) |
порядок проверяется конечным автоматом Run |
только структурно (без вердикта политики) |
«Нога» запроса (RunAgentInput) |
авторизуется tools[*].name; текст user- и system-сообщений, а также JSON context / forwardedProps / входного state проверяется на маркеры секретов и SSRF-URL (доменные хосты резолвятся и перепроверяются, закрывая DNS-rebinding) |
Да — отклонить до пересылки |
| Битые известные события | распознанный тип с отсутствующим/пустым обязательным полем нельзя инспектировать → обрабатывается по [policy].on_malformed_event (по умолчанию terminate) |
Да — по умолчанию fail-closed |
Что пересылается без инспекции¶
| Событие / ввод | Почему это важно |
|---|---|
| Семантика патча состояния | STATE_DELTA валидируется (корректный RFC 6902) и ограничивается, но прокси не моделирует итоговый документ — не может судить, к каким путям операции должны иметь доступ |
RAW, CUSTOM, REASONING_ENCRYPTED_VALUE |
непрозрачные — пересылаются как есть, не инспектируются |
| Неизвестные / будущие типы событий AG-UI | пересылаются сырыми |
Операционные ограничения¶
- Аутентификация выключена по умолчанию (открытый прокси). Задайте
[proxy].api_keysили поставьте перед Agate шлюз. См. Конфигурацию. - Бюджеты против DoS сегодня: глобальный лимит конкурентности, лимит размера
тела запроса, таймауты подключения/чтения, бюджет ответа на прогон
(
max_response_events/max_response_bytes), отрезающий зарвавшегося агента, и опциональный rate-лимит по IP клиента (rate_limit_per_second/rate_limit_burst, по умолчанию выключен), отбрасывающий потоки с429. IP берётся из пира соединения, поэтому он осмыслен только там, где Agate видит реального клиента. - Полнота аудита: записи ставятся в очередь ограниченного outbox, чья
заполненность экспортируется (
agate_audit_outbox_depth/_capacity). При полном outbox политика[audit].outbox_on_fullрешает:block(по умолчанию — backpressure на прокси, запись не теряется) илиshed(отбросить, с громким логом и счётчиком — не молча). Следите за gauge глубины и счётчиком дропов. - Память реплея между прогонами: по умолчанию выключена; включите
[policy.session_memory], чтобы запрещённый инструмент (по имени) карантинился до конца сессии — агент не сможет повторить его с другими аргументами в следующем прогоне. Она только добавляет отказ поверх stateless-политики. Ledger — в пределах процесса со скользящим TTL по умолчанию, либо Redis (backend = "redis"), общий для реплик и переживающий рестарт; Redis-backend fail-open — недоступный Redis деградирует до «нет памяти», никогда не wrong-allow. - TLS терминируется на прокси (необходимо для инспекции открытого текста);
по умолчанию выключен, настраивается в секции
[tls].
Дорожная карта¶
Оставшаяся работа — на перспективу: семантический allowlist путей состояния,
плагин-движок политик и sub-IP / per-API-key лимиты — упорядочена в
security-coverage-roadmap.md.
(Fail-closed для битых событий, правила запрета аргументов,
редакция секретов в результатах и состоянии, бюджеты ответа на прогон,
SSRF-скрин на обеих «ногах» с резолвом DNS против rebinding,
валидация/ограничение RFC 6902-патчей, сигнализация backpressure
audit-outbox с политикой block/shed, а также память реплея между прогонами
— в пределах процесса или на Redis — уже реализованы.)