LiteLLM снова скомпрометировали: как не потерять SSH-ключи и API-секреты через AI gateway в проде
Я — Denis Shokhirev, Agentic AI Systems Architect из Freiburg im Breisgau, Germany, и в DennisCraft AI Studio я собираю production AI-системы для DACH B2B на Claude, Supabase, n8n, Doppler и self-hosted Postgres. Самый неприятный момент в таких стеках — не падение модели и не рост latency, а когда AI gateway внезапно получает доступ к тому, что вообще не должен видеть: SSH-ключам, .env, service tokens и внутренним API-секретам. История с LiteLLM показательная именно поэтому. Если gateway стоит
Я — Denis Shokhirev, Agentic AI Systems Architect из Freiburg im Breisgau, Germany, и в DennisCraft AI Studio я собираю production AI-системы для DACH B2B на Claude, Supabase, n8n, Doppler и self-hosted Postgres. Самый неприятный момент в таких стеках — не падение модели и не рост latency, а когда AI gateway внезапно получает доступ к тому, что вообще не должен видеть: SSH-ключам, .env, service tokens и внутренним API-секретам.
История с LiteLLM показательная именно поэтому. Если gateway стоит между приложением, агентами и провайдерами моделей, он становится точкой концентрации секретов, логов, prompt payloads и иногда файловой системы. Компрометация такого узла — это уже не “инцидент в AI”, а обычный infrastructure breach с AI-спецификой: длинные prompt traces, tool calls, callback URLs, bearer tokens и привычка разработчиков прокидывать лишний контекст “для удобства”.
Почему AI gateway — это не просто прокси, а точка отказа по секретам
Многие команды смотрят на LiteLLM, OpenAI-compatible gateways и похожие прослойки как на удобный routing layer: единый endpoint, fallback между моделями, централизованный бюджет, общие логи. На практике gateway быстро превращается в место, где сходятся все секреты сразу: ключи от Anthropic и OpenAI, database credentials, internal service tokens, webhook signing secrets, иногда даже SSH для self-hosted inference или CI-задач.
OWASP в OWASP Top 10 for LLM Applications 2025 отдельно выделяет sensitive information disclosure и excessive agency как типовые риски для LLM-стеков: модельный слой часто получает больше данных и полномочий, чем нужно по задаче. Ссылка: https://genai.owasp.org/. В проде это выглядит банально: gateway логирует request body, туда попадает tool result, tool читает локальный файл, а в файле лежит токен, который никогда не должен был оказаться в observability-потоке.
Где именно утекают секреты
| Слой | Типичный риск | Что вижу в проде |
|---|---|---|
| HTTP gateway | Логирование полных payload | Authorization headers и tool outputs попадают в логи |
| Tool runner | Избыточные права на файловую систему | Агент читает ~/.ssh, .env, kubeconfig |
| n8n / automation | Секреты в переменных workflow | Webhook и API tokens попадают в execution history |
| Postgres / Supabase | Service-role ключи в agent context | Агент может читать больше таблиц, чем нужно |
Как строить защиту: считать gateway hostile-by-default
Я исхожу из простой модели: если AI gateway будет скомпрометирован, какой реальный ущерб он сможет нанести за 15 минут? Этот вопрос полезнее, чем спор о том, “безопасна ли конкретная библиотека”. Если ответ — “получит доступ ко всем продовым ключам”, архитектура уже плохая независимо от вендора.
1. Не держите секреты рядом с tool execution
Agent runtime и storage секретов должны быть разделены. Если у вас Claude Code, Anthropic SDK или внутренний tool runner может исполнять shell-команды, этот процесс не должен иметь прямой доступ к долгоживущим ключам. Я обычно выдаю короткоживущие credentials через отдельный сервисный слой и ограничиваю TTL до минут, а не дней.
#!/usr/bin/env bash
set -euo pipefail
export APP_ENV=production
export ANTHROPIC_API_KEY="$(doppler secrets get ANTHROPIC_API_KEY --plain)"
export DB_URL="$(doppler secrets get READONLY_DB_URL --plain)"
exec env -i \
PATH="/usr/bin:/bin" \
APP_ENV="$APP_ENV" \
ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
DB_URL="$DB_URL" \
python3 worker.pyЗдесь важен не Doppler сам по себе, а паттерн: чистое окружение через env -i, минимальный набор переменных, read-only database URL, никакого inheritance от shell пользователя.
2. Запретите доступ к домашней директории и локальным секретам
Команда часто считает, что если tool “только читает файлы проекта”, то риска нет. Но большинство утечек происходит не из репозитория, а из соседних путей: ~/.ssh, ~/.aws, ~/.config, локальные credentials для Docker или Git. Поэтому tool execution лучше запускать в отдельном контейнере с read-only bind mount только на рабочую директорию.
services:
agent-runner:
image: python:3.12-slim
working_dir: /app
volumes:
- ./workspace:/app:ro
read_only: true
tmpfs:
- /tmp
security_opt:
- no-new-privileges:true
cap_drop:
- ALLЭто не идеальная изоляция, но она сразу убирает класс проблем “агент случайно увидел домашнюю директорию разработчика”. Для regulated workloads этого уже мало, но это хороший базовый слой.
Что проверять в CI до выхода в прод
Утечка через gateway почти всегда усиливается двумя вещами: секрет уже лежит не там, где должен, и никто не проверил, что агентный код может к нему дотянуться. Поэтому в CI я добавляю не “AI security magic”, а обычные проверенные сканеры.
#!/usr/bin/env bash
set -euo pipefail
gitleaks detect --source . --no-git --exit-code 1
bandit -r . -x tests
semgrep --config auto .
echo "Static checks passed"gitleaks ловит ключи и токены в репозитории, bandit — опасные Python-паттерны, semgrep — широкий набор правил, включая shell execution, path traversal и небезопасную работу с вводом. Это не серебряная пуля, но это дешево и реально снижает поверхность атаки.
OpenAI Cookbook и документация Anthropic регулярно показывают, как организовывать tool use и structured outputs. Но такие примеры нельзя переносить в прод без threat model: sample code оптимизируется под понятность, а не под изоляцию секретов. Документация полезна как starting point, не как security baseline.
Минимальная политика для gateway
Если у вас уже стоит LiteLLM или другой совместимый gateway, я бы проверил 5 вещей:
- отключено ли логирование полных request/response body;
- маскируются ли Authorization headers и tool outputs;
- разделены ли prod и staging ключи физически, а не тегом;
- есть ли egress control для tool runner;
- можно ли быстро отозвать секреты без пересборки всего пайплайна.
Практическая схема для production agent systems
В моих системах для DACH-клиентов я стараюсь не давать gateway ничего лишнего. Модельному слою нужен только доступ к model provider API и к узкому набору инструментов. Доступ к Postgres идет через отдельный backend с row-level ограничениями, а не через service-role ключ внутри prompt pipeline. Supabase удобен, но service_role в agent context — плохая идея почти всегда.
from anthropic import Anthropic
import os
client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=512,
system="You may call only approved tools. Never request secrets.",
messages=[{"role": "user", "content": "Summarize ticket status"}]
)
print(message.content)Ключевой момент здесь не SDK, а то, чего здесь нет: нет database superuser credentials, нет SSH, нет file-system tooling по умолчанию. Все потенциально опасные действия вынесены в отдельные сервисы с audit trail.
FAQ
Стоит ли полностью отказаться от LiteLLM?
Не обязательно. Проблема обычно не в одном названии, а в том, что gateway получает слишком много прав и слишком много данных. Если он изолирован, мало что логирует и не видит долгоживущие секреты, риск заметно ниже.
Можно ли хранить API-ключи в переменных окружения?
Да, но с ограничениями. Переменные окружения приемлемы для короткоживущих процессов, если они не протекают в логи, debug dumps и дочерние процессы без контроля.
Нужен ли отдельный контейнер для tool execution?
Да, если агент умеет читать файлы, ходить в сеть или вызывать shell. Даже простая контейнеризация с read-only mounts и урезанными capabilities заметно уменьшает blast radius.
Какой первый шаг самый полезный?
Отключите полные логи prompt/tool payloads и проверьте, какие секреты реально доступны процессу gateway. Обычно уже на этом этапе обнаруживается больше лишнего доступа, чем ожидалось.
Что делать после возможной компрометации?
Считать все видимые gateway секреты скомпрометированными: ротация ключей, ревизия логов, аудит tool permissions, проверка outbound трафика. Если это не делается за часы, а не за дни, ваш incident path слишком хрупкий.
На каком этапе вашего LLM pipeline сегодня ловится больше всего проблем в проде — статический анализ, изоляция runtime, контроль egress или ручной review привилегированных tools? Мне правда интересно сравнить это с тем, что я вижу у команд в regulated европейских стеках.
I run a free 30-min stack audit for DACH founders building AI in regulated markets. DM me on LinkedIn or write to @ger_dennis_ai.
Превратить процесс в систему, которая работает
Продакшн-качество, а не демо.