Перейти к содержанию

HTTP-заголовки ответа Gateway

AppSec.AIGate добавляет служебные заголовки X-LLMFW-* к каждому ответу Gateway. Они предназначены для интеграции с downstream-системами: WAF (Cloudflare, Kong, NGINX, Envoy), reverse-proxy, инструменты трассировки, корпоративные системы мониторинга. Заголовки позволяют принимать решения по результату работы AppSec.AIGate, не читая тело ответа.

Сводная таблица

Заголовок Значения Когда выставляется
X-LLMFW-Action ALLOW / BLOCK / SANITIZE / MONITOR_ONLY / REJECT На штатных исходах инспекции (см. ниже)
X-LLMFW-Risk-Score Число формата ^\d\.\d{3}$ (например 0.847) Вместе с X-LLMFW-Action (0.000 для ALLOW без риска)
X-LLMFW-Risk-Severity CRITICAL / HIGH / MEDIUM / LOW Только когда PDP вернул непустой severity
X-LLMFW-Policy-Version Строка с версией политики (например v2.4.0-dynamic) Только когда PDP вернул версию политики
X-LLM-Firewall-Trace-ID Идентификатор трассировки (UUID/OpenTelemetry trace id) Всегда (на входе обработчика)
X-LLMFW-Would-Block true Только в режиме мониторинга
X-LLMFW-Would-Action Действие, которое было бы применено: BLOCK / SANITIZE Только в режиме мониторинга
X-LLM-Firewall-Action То же, что X-LLMFW-Action (+ BLOCKED_NO_PROFILE в edge-case) Вместе с X-LLMFW-Action (legacy)
X-LLM-Firewall-Upstream-URL URL upstream-эндпоинта Ошибка upstream: timeout (504) или transport (502)
Retry-After Число секунд до повтора Vault недоступен при vault_unavailable_action=block (503)

Подробное описание

X-LLMFW-Action

Итоговое комбинированное решение Gateway по запросу и ответу (отдельных X-LLMFW-Response-* заголовков нет): блокировка ответа LLM эскалирует значение до BLOCK, маскирование ответа — до SANITIZE, иначе сохраняется решение по запросу.

  • ALLOW — запрос разрешён и проксирован к LLM без изменений.
  • BLOCK — запрос или ответ LLM заблокирован; клиент получил ошибку.
  • SANITIZE — запрос или ответ модифицирован (например, ПДн заменены масками).
  • MONITOR_ONLY — запрос проксирован к LLM без изменений, но детекторы зафиксировали событие; решение «как если бы enforcement был включён» — в заголовке X-LLMFW-Would-Action.
  • REJECT — потоковый запрос отклонён профилем (streaming_strategy=reject, HTTP 422).

Заголовок выставляется только на штатных исходах инспекции. Он отсутствует на путях, где инспекция не выполнялась: passthrough (неактивный профиль или не-chat-трафик), ошибки upstream (502/504), ранние ошибки разбора запроса (400). На таких путях присутствует только X-LLM-Firewall-Trace-ID.

X-LLMFW-Risk-Score

Числовая оценка риска по единой шкале 0.000–1.000, всегда с тремя знаками после точки (формат ^\d\.\d{3}$). Что считается, как формируется и какие веса используются — см. Оценка риска.

Удобно для пороговой логики на стороне WAF:

if (X-LLMFW-Risk-Score >= 0.800) → дополнительный аудит / алерт

X-LLMFW-Risk-Severity

Классификация risk_score по уровню серьёзности. Значения и пороги — см. Оценка риска. Подходит для правил вида «логировать всё HIGH+ в SIEM» без явных числовых порогов в WAF.

Заголовок выставляется, только если PDP вернул непустой severity. Для низкорискованного ALLOW severity пустой — заголовок не добавляется вовсе. Значения NONE не существует: отсутствие заголовка означает, что риск не классифицирован.

X-LLMFW-Policy-Version

Версия политики (OPA-бандла), на основе которой принято решение. Используется для аудита и сопоставления событий с конкретной версией политики, действовавшей в момент запроса. Выставляется, только когда PDP вернул версию политики.

X-LLM-Firewall-Trace-ID

Идентификатор трассировки запроса. Это канонический заголовок трассировки в AppSec.AIGate — он совпадает по содержанию с OpenTelemetry trace_id и одинаков во всех записях логов, событий и метрик, связанных с этим запросом. Используется для:

  • сопоставления HTTP-ответа с записью в логе Gateway / детекторов;
  • сквозного поиска в SIEM по конкретному запросу;
  • корреляции с распределённой трассировкой (Jaeger, Tempo и т. п.).

Обратите внимание

Канонический заголовок трассировки — именно X-LLM-Firewall-Trace-ID. Прежние черновики документации могли упоминать заголовок X-LLMFW-Trace-ID — этот вариант устарел и в продуктивных версиях не выставляется.

X-LLMFW-Would-Block / X-LLMFW-Would-Action

Эти заголовки появляются только в режиме мониторинга (Monitor Mode в профиле). Они сообщают, как поступил бы Gateway, если бы профиль работал в режиме enforcement:

  • X-LLMFW-Would-Block: true — запрос был бы заблокирован.
  • X-LLMFW-Would-Action: BLOCK или SANITIZE — конкретное действие, которое применилось бы.

Используются для оценки полноты и корректности политики до её перевода в продуктив. Подробнее — см. Оценка риска → Режим мониторинга.

X-LLM-Firewall-Action

Legacy-заголовок, дублирующий X-LLMFW-Action. Сохранён для обратной совместимости с интеграциями, написанными до введения единого префикса X-LLMFW-*. Новый код рекомендуется писать на X-LLMFW-Action.

В одном edge-case этот legacy-заголовок выставляется в одиночку: если провайдер найден, но у него нет активного профиля (HTTP 422), Gateway возвращает X-LLM-Firewall-Action: BLOCKED_NO_PROFILE, при этом X-LLMFW-Action не выставляется.

X-LLM-Firewall-Upstream-URL

URL upstream-эндпоинта LLM, при обращении к которому произошла ошибка соединения. Выставляется при таймауте upstream (HTTP 504) или транспортной ошибке (HTTP 502) — помогает downstream-системам и диагностике определить недоступный backend, не разбирая тело ответа. Содержит baseURL из конфигурации провайдера (например https://api.openai.com) — это системный идентификатор, не ПДн.

Не включайте учётные данные в URL провайдера

Если API-ключ ошибочно встроен прямо в URL провайдера (query-параметром или в userinfo), он попадёт в этот заголовок и далее — в логи прокси/WAF. Это угроза компрометации ключа. Передавайте учётные данные только через отведённые поля авторизации, а не в URL.

Retry-After

Стандартный HTTP-заголовок (RFC 7231): число секунд до повторного запроса. Выставляется, когда Tokenization Vault недоступен, а профиль настроен на блокировку при его недоступности (vault_unavailable_action=block) — Gateway возвращает HTTP 503 с Retry-After.

Чего нет в заголовках

Сознательно не выводятся в HTTP-заголовки:

Данные Почему не в заголовках Где смотреть
Разбивка risk_breakdown Размер заголовков (несколько килобайт), риск утечки структуры детекторов Запись события / API /api/v1/security-events/{id}
Найденные PII-сущности Категорически нельзя — это сами персональные данные Только запись события в защищённом хранилище
Текст промпта / ответа PII-утечка через прокси-логи Запись события
Тексты сработавших правил Custom Policy Может содержать чувствительные паттерны Запись события

Эти данные доступны только через защищённый канал — API событий или Admin UI.

Пример HTTP-ответа

HTTP/1.1 451 Unavailable For Legal Reasons
Content-Type: application/json
X-LLMFW-Action: BLOCK
X-LLM-Firewall-Action: BLOCK
X-LLMFW-Risk-Score: 0.847
X-LLMFW-Risk-Severity: HIGH
X-LLMFW-Policy-Version: v2.4.0-dynamic
X-LLM-Firewall-Trace-ID: 7f3a4b2c-9d1e-4f0a-b8c5-1234567890ab

{"error":{"code":"REQUEST_BLOCKED","message":"Request blocked by security policy"}}

Пример в режиме мониторинга (запрос проксирован, но был бы заблокирован):

HTTP/1.1 200 OK
Content-Type: application/json
X-LLMFW-Action: MONITOR_ONLY
X-LLM-Firewall-Action: MONITOR_ONLY
X-LLMFW-Risk-Score: 0.665
X-LLMFW-Risk-Severity: HIGH
X-LLMFW-Would-Block: true
X-LLMFW-Would-Action: BLOCK
X-LLMFW-Policy-Version: v2.4.0-dynamic
X-LLM-Firewall-Trace-ID: 8a2b3c4d-e5f6-7a8b-9c0d-fedcba987654

{"id":"chatcmpl-abc","choices":[]}

Дополнительная информация