PII и секреты не должны попадать к LLM-провайдеру.
Прозрачный прокси: модель видит плейсхолдеры, клиент — оригиналы. В приложении меняется только base URL.
Быстрый старт · Возможности · Веб-консоль · Сравнение с альтернативами · Документация
Клиенты обращаются к прокси вместо провайдера. По пути к модели ~265 встроенных
regex-правил заменяют найденные чувствительные значения плейсхолдерами вида
<EMAIL_1>, а в ответе — включая SSE-стриминг токен-за-токеном — возвращают
оригиналы. Модель никогда не видит чувствительные данные; клиент никогда не
видит плейсхолдеры.
sequenceDiagram
participant C as Клиент
participant G as guardrails-llm-filter
participant P as LLM-провайдер
C->>G: POST /v1/chat/completions — "пишите на a@b.com"
Note over G: скан ~260 regex-правил,<br/>замена значений на плейсхолдеры
G->>P: маскированный запрос — "пишите на #60;EMAIL_1#62;"
P-->>G: ответ с плейсхолдерами (JSON или SSE-кадры)
Note over G: демаскирование — полное тело<br/>или токен-за-токеном по SSE-кадрам
G-->>C: ответ с оригиналами — "пишите на a@b.com"
Envoy или сайдкара в пути нет — сервис сам является data-plane. Родственный
проект guardrails-llm-filter-extproc
упаковывает тот же движок как gRPC-сайдкар Envoy ext_proc.
- 🛡️ ~265 встроенных правил: учётные данные, API-ключи, access-токены, IP-адреса, персональные данные (российские PII, карты, IBAN, СНИЛС/ИНН/ОГРН — с проверкой контрольных сумм).
- 🔄 Оригиналы возвращаются в ответ автоматически — включая потоковые ответы и аргументы вызова инструментов (tool-call). Клиент видит настоящие данные, модель — только заглушки.
- 🔌 OpenAI и Anthropic из коробки:
/v1/chat/completions,/v1/responses,/v1/messages— JSON и стриминг. - ⚡ Микросекунды на data-path: детекция — regex + валидаторы контрольных сумм, без ML-инференса и внешних вызовов (сравнение с альтернативами).
- 🟢 Fail-open по замыслу: любая внутренняя ошибка пропускает трафик, а не ломает его.
- 👁️ Detect (shadow) режим: оцените, что было бы замаскировано, не трогая трафик, и
переключитесь на
enforceчерез API без передеплоя. - 🎛️ Встроенная веб-консоль: обзор, правила, песочница, настройки, журнал аудита и мониторинг.
- 📊 Наблюдаемость: метрики Prometheus, готовый дашборд Grafana (пошаговое подключение), аудит-трейл.
Готовый образ: направьте его на вашего LLM-провайдера — и шлите запросы на :8080
вместо провайдера. В клиенте меняется только base URL:
docker run --rm -p 8080:8080 -p 9080:9080 \
-e GUARDRAILS_UPSTREAM_BASE_URL=https://foundation-models.api.cloud.ru \
ghcr.io/cloud-ru-tech/guardrails-llm-filter:latest
# в другом терминале — тот же запрос, что вы бы послали провайдеру, но другой хост:
curl -sS http://localhost:8080/v1/chat/completions \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $CLOUDRU_API_KEY" \
-d '{"model":"ai-sage/GigaChat3-10B-A1.8B","messages":[{"role":"user","content":"email me at a@b.com"}]}'Провайдер получает <EMAIL_1> вместо адреса; в ответе, который получаете вы, оригинал
восстановлен. Веб-консоль — на http://localhost:9080.
Сборка из исходников вместо образа
make build
GUARDRAILS_UPSTREAM_BASE_URL=https://foundation-models.api.cloud.ru \
./bin/guardrails-llm-filterКлюч
CLOUDRU_API_KEYи список доступных моделей — в документации Cloud.ru Foundation Models.
cd examples/quickstart
docker compose up --build # guardrails-llm-filter + фейковый LLM, который отвечает эхом
bash demo.sh # шлёт промпты с выдуманными email и картой; показывает,
# что ушло провайдеру (замаскировано) и что вернулось клиентуДемо включает аудит и сохранение маскированных текстов запроса/ответа — откройте консоль на http://localhost:9080 и посмотрите страницы «Обзор» и «Аудит» (скриншоты — ниже).
Управление правилами, настройками и аудит-трейлом вшито в бинарь и отдаётся на / на
management-порту (:9080) — тот же образ, без отдельного веб-сервера и без CORS.
Консоль включена по умолчанию (
GUARDRAILS_UI_ENABLED=falseотключает), делит границу доверия config API и работает только внутри кластера — никогда публичный ingress. Есть переключатель светлой/тёмной темы.
Весь путь запроса проходит в одном обработчике на одной реплике: прочитать запрос клиента → замаскировать → переслать провайдеру → получить ответ и восстановить в нём оригиналы (целиком, а для потоковых ответов — по мере поступления) → отдать клиенту. Запрос и ответ на него обрабатываются вместе, поэтому таблица «заглушка → оригинал» просто хранится в памяти процесса, пока идёт запрос. Отдельное хранилище для прохождения трафика не нужно.
- Поддерживаемые API: OpenAI
/v1/chat/completions,/v1/responses, Anthropic/v1/messages— обычные и потоковые ответы, включая аргументы вызова инструментов. Пути сравниваются по окончанию, поэтому вложенные варианты (/openai/v1/chat/completions) работают сразу; свои пути задаются черезGUARDRAILS_PATHS. Если тело запроса не удаётся разобрать, он проходит без маскирования (безопасное поведение при сбое) и увеличивает счётчикextproc_guardrails_unsupported_body_schema_total. Любой другой путь просто проксируется провайдеру без изменений. - Что делает сервис с находкой: только заменяет значение на заглушку. Запросы он никогда не блокирует.
Полный разбор пути запроса, движок правил и устройство хранилища — в
docs/.
Ниша guardrails-llm-filter — двустороннее маскирование как drop-in прокси:
клиент меняет только base URL, провайдер видит плейсхолдеры, клиент получает
оригиналы обратно — в том числе внутри SSE-стриминга токен-за-токеном. Большинство
инструментов в этой области делают одностороннюю редакцию («замазали и забыли»)
или требуют встраивания в код приложения. Состояние на июль 2026, по официальной
документации проектов:
| Возможность | guardrails- llm-filter |
LiteLLM + Presidio |
Kong AI Gateway |
Portkey | NeMo Guardrails |
LLM Guard | Presidio | Bedrock Guardrails |
|---|---|---|---|---|---|---|---|---|
| Форм-фактор | прокси, один Go-бинарь |
шлюз (Python) + 2 контейнера |
шлюз + отдельный PII-сервис |
шлюз (TypeScript) |
фреймворк (Python) |
библиотека + API |
библиотека / REST-сервисы |
managed-фича AWS |
| Drop-in прокси (меняется только base URL) | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | |
| Маскирование запросов к LLM | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
| Восстановление оригиналов в ответе | ✅ | ❌4 | ❌ | ✅ | ❌ | |||
| Восстановление в SSE-стриме токен-за-токеном | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Детекция секретов и ключей (не только PII) | ✅ | — | — | ✅ | — | |||
| Российские PII с контрольными суммами (СНИЛС/ИНН/ОГРН) | ✅ | — | — | — | — | — | — | — |
| Shadow-режим (скан и метрики без изменения трафика) | ✅ | ✅ | — | — | — | — | — | — |
| Веб-консоль управления из коробки | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ||
| Без ML-инференса на data-path (микросекунды) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Self-hosted | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| Лицензия | Apache-2.0 | MIT10 | Enterprise | MIT | Apache-2.0 | MIT11 | MIT | проприетарно |
✅ заявлено в документации и работает из коробки ·
Отличия одним абзацем: детекция здесь — regex + валидаторы контрольных сумм (Luhn, СНИЛС, ИНН, ОГРН, IBAN), поэтому data-path обходится без ML-моделей и внешних вызовов; ~260 правил включают каталог секретов, производный от gitleaks; маскируются и аргументы tool-call; fail-open инвариант — никакая внутренняя ошибка не блокирует трафик.
Когда выбрать другое. Нужен контекстный ML-NER для свободного текста на
многих языках — Presidio (или LiteLLM с ним). Нужен полновесный AI-шлюз
(маршрутизация, ключи, бюджеты, 100+ провайдеров) — LiteLLM или Portkey, PII там
будет попроще. Уже стоит Kong Enterprise — логично включить ai-sanitizer. Вся
инфраструктура в AWS Bedrock — Guardrails ближе всего. Нужны диалоговые рельсы и
защита от джейлбрейков, а не маскирование — NeMo Guardrails решает другую задачу.
Детекция здесь — regex + валидаторы, но на публичном датасете
hivetrace/pii-bench
(1810 примеров, 13 типов ПДн) она конкурентна с ML: span-level F1 93.1 при
precision 99.9% — выше, чем у полного pipeline GLiNER Guard (модель + regex, 84.4).
Сырые ML-модели проваливаются на структурированном PII (ИНН/ОГРН/КПП/карта) и
добирают до рабочих цифр теми же regex-правилами. Разбор по всем типам,
методика и источники — в MULTIBENCH.md.
| Модель | Датасет | F1 | recall | precision |
|---|---|---|---|---|
| guardrails (наш) | hivetrace/pii-bench | 93.1 | 87.2 | 99.9 |
| guardrails (наш) | alexen2 | 89.8 | 82.2 | 98.9 |
| guardrails (наш) | alrosait | 82.9 | 75.1 | 92.4 |
| GLiGuard pipeline (модель+regex)12 | hivetrace/pii-bench | 84.4 | — | — |
| GLiGuard Omni raw12 | hivetrace/pii-bench | 72.8 | — | — |
| GLiNER2-Multi raw12 | hivetrace/pii-bench | 68.8 | — | — |
| GLiGuard uni raw12 | hivetrace/pii-bench | 24.2 | — | — |
F1 моделей — из статьи GLiNER Guard (arXiv 2605.05277); авторы публикуют только F1, поэтому recall/precision — «—». Сторонних замеров на alexen2/alrosait нет.
Все переменные с префиксом GUARDRAILS_. Обычно достаточно нескольких:
| Переменная | По умолчанию | Описание |
|---|---|---|
GUARDRAILS_UPSTREAM_BASE_URL |
— | обязательно: базовый URL upstream LLM-провайдера |
GUARDRAILS_LISTEN_ADDR |
:8080 |
data-plane (сюда обращаются клиенты) |
GUARDRAILS_MODE |
enforce |
detect = shadow-режим: скан + метрики/аудит, трафик не тронут |
GUARDRAILS_STORE_BACKEND |
in_memory |
redis | postgres — для нескольких реплик и персистентности |
GUARDRAILS_AUDIT_ENABLED |
false |
аудит-трейл маскирования + страницы «Обзор»/«Аудит» в консоли |
GUARDRAILS_API_ADDR |
:9080 |
config API + веб-консоль |
Полный разбор резолюции настроек и матчинга путей — в docs/configuration/.
Полный справочник переменных окружения
| Переменная | По умолчанию | Описание |
|---|---|---|
GUARDRAILS_LISTEN_ADDR |
:8080 |
data-plane HTTP-адрес (сюда обращаются клиенты) |
GUARDRAILS_UPSTREAM_BASE_URL |
— | обязательно: базовый URL upstream LLM-провайдера; путь запроса дописывается к нему |
GUARDRAILS_UPSTREAM_TIMEOUT |
120s |
таймаут заголовков ответа upstream (время до первого байта); не ограничивает стриминговое тело, чья жизнь следует за соединением клиента; 0 отключает |
GUARDRAILS_UPSTREAM_MAX_IDLE_CONNS |
100 |
пул соединений upstream: максимум idle-соединений |
GUARDRAILS_UPSTREAM_MAX_IDLE_CONNS_PER_HOST |
100 |
пул соединений upstream: максимум idle на хост |
GUARDRAILS_UPSTREAM_IDLE_CONN_TIMEOUT |
90s |
пул соединений upstream: таймаут idle-соединения |
GUARDRAILS_UPSTREAM_PATH_BASE_URLS |
— | per-path переопределения базового URL как пары path=url через запятую (например, /v1/messages=https://api.anthropic.com); путь не из списка использует UPSTREAM_BASE_URL |
GUARDRAILS_UPSTREAM_INSECURE_SKIP_VERIFY |
false |
|
GUARDRAILS_MAX_REQUEST_BYTES |
33554432 (32 MiB) |
лимит тела запроса до маскирования; превышение → 413; 0 отключает |
GUARDRAILS_LOG_LEVEL |
info |
debug | info | warn | error |
GUARDRAILS_LOG_FORMAT |
json |
json | text |
GUARDRAILS_METRICS_PORT |
9090 |
порт метрик Prometheus |
GUARDRAILS_GRPC_ADDR |
:9000 |
management gRPC-адрес (GuardrailsApi); REST-API проксирует на него |
GUARDRAILS_GRPC_SECURE |
false |
self-signed TLS на management gRPC-listener; по умолчанию выкл (API рассчитан на работу внутри кластера) |
GUARDRAILS_ENABLED |
true |
глобальный вкл/выкл (seed-значение) |
GUARDRAILS_MODE |
enforce |
detect = shadow-режим: скан + метрики/аудит, трафик не тронут (seed) |
GUARDRAILS_DATA_TYPES |
1,2,3,4,5,6 |
включённые типы данных, числа или имена (6/CUSTOM включает кастомные правила из API) |
GUARDRAILS_KEYWORD_PREFILTER_ENABLED |
false |
сохраняющий полноту keyword-пре-фильтр (ускоряет скан) |
GUARDRAILS_MASK_PARALLEL_MIN_BYTES |
8192 |
суммарный размер текстов (байты), с которого скан распараллеливается по полям (нужно ≥2 поля); 0 — встроенное значение |
GUARDRAILS_PATHS |
3 стандартных пути | пары path:format (chat_completions, messages, responses); суффиксный матчинг, подмешиваются поверх дефолтов |
GUARDRAILS_OVERRIDE_HEADER |
x-guardrails-data-types |
per-request заголовок сужения (потребляется, не форвардится); пусто отключает |
GUARDRAILS_SETTINGS_REFRESH_INTERVAL |
30s |
интервал перечитывания настроек (сходимость реплик); 0 отключает |
GUARDRAILS_RULES_REFRESH_INTERVAL |
30s |
интервал перечитывания кастомных правил; 0 отключает |
GUARDRAILS_RULES_REGEX_RULES_FILE |
./configs/guardrails_regex_rules.yaml |
ручной файл правил |
GUARDRAILS_RULES_GITLEAKS_REGEX_RULES_FILE |
./configs/guardrails_regex_rules.gitleaks.generated.yaml |
генерируемый файл правил |
GUARDRAILS_RULES_MAX_CUSTOM |
500 |
лимит числа кастомных правил через API (каждое исполняется на каждом запросе); 0 отключает |
GUARDRAILS_RULES_MAX_PATTERN_LEN |
4096 |
лимит длины regex кастомного правила; 0 отключает |
GUARDRAILS_HEADERS_DATA_TYPES_HEADER |
x-guardrails-data-types-triggered |
заголовок ответа со сработавшими типами данных |
GUARDRAILS_HEADERS_TRIGGERED_RULES_HEADER |
x-guardrails-triggered-rules |
заголовок ответа со сработавшими ID правил |
GUARDRAILS_HEADERS_EXPOSE_TRIGGERED_RULES |
false |
эмитить заголовок сработавших правил |
GUARDRAILS_STORE_BACKEND |
in_memory |
in_memory | redis | postgres — хранит кастомные правила, настройки и аудит (не masking state data-path, который в процессе) |
GUARDRAILS_STORE_MASKING_TTL |
15m |
страховочный TTL masking state (для межрепличного fallback); должен превышать самый длинный стриминговый ответ |
GUARDRAILS_STORE_REDIS_ADDR |
redis:6379 |
адрес redis-бэкенда |
GUARDRAILS_STORE_REDIS_PASSWORD |
— | пароль redis |
GUARDRAILS_STORE_REDIS_DB |
0 |
база redis |
GUARDRAILS_STORE_POSTGRES_DSN |
— | DSN postgres |
GUARDRAILS_STORE_ENCRYPTION_ENABLED |
false |
AES-256-GCM-шифрование masking state в redis/postgres на месте (no-op для in_memory) |
GUARDRAILS_STORE_ENCRYPTION_KEY |
— | base64 32-байтный ключ (openssl rand -base64 32); обязателен при включённом шифровании |
GUARDRAILS_API_ADDR |
:9080 |
адрес config API; пусто отключает API |
GUARDRAILS_UI_ENABLED |
true |
отдавать встроенную веб-консоль на / на порту API (no-op, если бинарь собран без UI) |
GUARDRAILS_AUDIT_ENABLED |
false |
аудит-трейл маскирования + эндпоинты /v1/audit |
GUARDRAILS_AUDIT_STORE_MASKED_TEXTS |
false |
дополнительно хранить маскированные тексты запроса (пользовательский контент — см. SECURITY.md) |
GUARDRAILS_AUDIT_STORE_MASKED_RESPONSE_TEXTS |
false |
дополнительно хранить маскированные тексты ответа модели (тот же класс чувствительности) |
GUARDRAILS_AUDIT_STORE_ORIGINAL_TEXTS |
off |
хранить оригинал за каждым плейсхолдером для «показа по наведению» в UI: off | plain | encrypted. encrypted переиспользует ключ AES-256-GCM хранилища и требует GUARDRAILS_STORE_ENCRYPTION_ENABLED. БЕЗОПАСНОСТЬ: plain/encrypted сохраняют сырые чувствительные данные — ограничьте доступ к хранилищу |
GUARDRAILS_AUDIT_RETENTION |
24h |
сколько хранятся аудит-записи |
GUARDRAILS_AUDIT_MAX_ENTRIES |
10000 |
только для in_memory: лимит аудит-записей (вытесняется старейшее) |
Типы данных: 1 CREDENTIALS, 2 API_KEYS, 3 ACCESS_TOKENS, 4 IP_ADDRESSES,
5 PERSONAL_DATA, 6 CUSTOM. Имена принимаются регистронезависимо всюду, где принимаются
числа.
Env-значения только засевают глобальные настройки на первом старте; далее источник
истины — config API (GET/PUT /v1/settings), перечитывается каждые
SETTINGS_REFRESH_INTERVAL. Per-request override-заголовок работает только на сужение:
он может пересечь глобальные типы данных, но никогда не расширить их; none пропускает
маскирование для запроса; неразбираемый ввод полностью игнорируется (склон к защите).
Заголовок считается доверенным: если сервис доступен недоверенным клиентам, вырезайте его
на фронтирующем шлюзе — иначе клиент может сузить маскирование собственных запросов.
Отдельный HTTP API (GUARDRAILS_API_ADDR, по умолчанию :9080) управляет своими
правилами и настройками и отдаёт журнал аудита: GET/PUT /v1/settings,
GET/POST/DELETE /v1/rules[...], PATCH /v1/rules/{id} (включить/выключить),
GET /v1/audit/records. API описан в proto-контракте (сервис GuardrailsApi): из него
генерируются gRPC-сервер на GUARDRAILS_GRPC_ADDR (:9000) и REST-обёртка над ним на
GUARDRAILS_API_ADDR (:9080). Общая спецификация OpenAPI v2 лежит в
service.swagger.json. У API нет своей аутентификации —
закрывайте его на уровне сети: держите внутри кластера и не выставляйте наружу.
Пример — добавить своё правило (оно проверяется так же, как встроенные, и применяется сразу, без перезапуска):
curl -X POST localhost:9080/v1/rules -H 'Content-Type: application/json' -d '{
"rule_id": "acme_token",
"name": "ACME internal token",
"data_type": 6,
"regex": "\\bacme-[0-9a-f]{8}\\b",
"masking": {"placeholder": "ACME_TOKEN"}
}'Не забудьте включить тип данных 6 (custom) в настройках, иначе такие правила работать не
будут.
- Health:
GET /healthz(liveness) иGET /readyz(readiness) на data-plane порту. - Метрики: Prometheus на
GUARDRAILS_METRICS_PORT(/metrics), namespaceextproc_guardrails. Правила алертов и дашборд Grafana — вdeploy/; пошаговое подключение Prometheus и Grafana — вdocs/monitoring/и на странице «Мониторинг» консоли. - Аудит-трейл (
GUARDRAILS_AUDIT_ENABLED): одна запись на маскированный запрос с задействованными правилами, типами данных и плейсхолдерами (страница «Аудит» в консоли).
Форма деплоя: один контейнер, три порта; внешнее хранилище опционально (нужно, когда реплик больше одной или правила/аудит должны переживать рестарт):
flowchart LR
C["Клиенты (SDK OpenAI / Anthropic)"] -->|":8080 data-plane"| G["guardrails-llm-filter"]
O["Оператор / браузер"] -->|":9080 config API + консоль"| G
M["Prometheus"] -->|":9090 /metrics"| G
G -->|"маскированные запросы"| P["LLM-провайдер"]
G <-->|"правила, настройки, аудит"| S[("in_memory / redis / postgres")]
Kustomize-манифесты — в deploy/kubernetes/: Deployment (HTTP-пробы
/healthz + /readyz), Service, ConfigMap и Secret. Задайте GUARDRAILS_UPSTREAM_BASE_URL
в ConfigMap. Distroless-образ собирается Dockerfile.
make build # бинарь -> ./bin/guardrails-llm-filter
make frontend # собрать SPA-консоль в frontend/dist (вшивается в make build)
make test # go test -race ./... (postgres-хранилище нужен Docker; авто-скип)
make test-short # без Docker
make lint # golangci-lint run
make rules-gen # перегенерировать gitleaks-файл правил из configs/gitleaks.toml
make demo-up # сквозное демо: guardrails-llm-filter + mock LLM (examples/quickstart)См. CONTRIBUTING.md.
Инженерная документация — в docs/, с mermaid-диаграммами по каждой
подсистеме:
| Раздел | Про что |
|---|---|
| Архитектура | компоненты, горячий путь, инварианты (fail-open, только маскировать/пропускать) |
| Конфигурация | все env-переменные, резолюция настроек, матчинг путей |
| Движок правил | источники правил, скан-пайплайн, валидаторы, демаскирование и SSE |
| Хранилище | роли стора, бэкенды, TTL и шифрование masking state |
| API | management API (gRPC + REST), коды ошибок, поток мутации правила |
| Эксплуатация | порты, справочник метрик, алерты, режимы отказа |
| Мониторинг | пошаговое подключение Prometheus и Grafana, пример дашборда |
| Разработка | сборка, тесты, генерируемые файлы, демо и dev-цикл консоли |
Apache-2.0 — см. LICENSE. Включает правила, производные от gitleaks (MIT), см. NOTICE.
Сделано в Cloud.ru · нашли баг или не хватает правила — issue и PR приветствуются · ⭐ помогает проекту
Footnotes
-
Маскирование label-плейсхолдерами (
[FIRST_NAME]) через Presidio/GLiNER, без карты восстановления. ↩ -
output_parse_piiвосстанавливает по карте вида<PERSON>— повторные сущности одного типа могут коллизировать; стриминг — частично. ↩ -
recover_redactedвосстанавливает только значения из запроса; response-фаза плагинов несовместима со стримингом. ↩ -
Документация Portkey: «redaction is irreversible by design». ↩
-
Деанонимизация только для оператора
encrypt(AES) — расшифровка, а не восстановление плейсхолдеров. ↩ -
hide_secrets— в платном enterprise-каталоге. ↩ -
Через пользовательские regex-паттерны, готового каталога секретов нет. ↩ ↩2
-
Kong Manager — в Enterprise-тире. ↩
-
Контрольная панель — в hosted-облаке Portkey; в self-hosted OSS-шлюзе консоли нет. ↩
-
Ядро MIT, часть guardrail-функций — в платном enterprise-каталоге. ↩
-
Репозиторий архивирован в июле 2026 (после поглощения Protect AI компанией Palo Alto Networks). ↩
-
GLiNER Guard / GLiNER2 — энкодеры для zero-shot PII/NER; «raw» = только модель, «pipeline» = модель + детерминированные regex-правила (их же production-режим). ↩ ↩2 ↩3 ↩4






