Как безопасно хранить API-ключи для AI-сервисов
API-ключ открывает доступ к балансу и моделям, поэтому обращаться с ним нужно как с паролем от платёжного инструмента. Ниже — где хранить секрет, что его убивает и как пережить утечку.
Ключ — это деньги, а не строка
Скомпрометированный API-ключ — это открытый кошелёк: любой, кто его получил, тратит ваш баланс на свои запросы. Поэтому модель угроз строится не вокруг «секретности ради секретности», а вокруг денег: где ключ лежит, кто его читает, что ограничивает ущерб.
Два числа определяют blast radius: spend limit ключа и скорость, с которой вы замечаете аномалию. Всё ниже — про то, как сузить оба.
Где должен находиться ключ
Единственное допустимое место — секреты среды выполнения на сервере: env-переменные процесса, secret manager, хранилище CI. Клиентское приложение ходит в ваш backend, backend подставляет Authorization и идёт в NormaHub.
Разделяйте ключи: тестовый для разработки, отдельный для продакшена, отдельный для каждого внешнего сервиса и агента. Отзыв одного ключа тогда не останавливает весь продукт.
- ключ читается только серверным кодом
- на каждое окружение и интеграцию — свой ключ
- лимит расходов задан до первого запроса
Что никогда не должно видеть секрет
Постоянный ключ в браузере, мобильном приложении или URL — это уже утечка, даже если «никто не смотрит». Секреты оседают и там, где их не ждут: логи reverse-proxy, crash-дампы, тексты исключений HTTP-клиента, слои Docker-образов.
Проверяйте не только исходники. Сканер секретов должен гоняться по репозиториям регулярно, а не один раз при настройке.
- префиксы публичных переменных (NEXT_PUBLIC_, VITE_)
- localStorage и query string
- публичный JS-bundle и мобильные сборки
- .env в Git, CI-артефакты, docker history
Ротация после подозрения на утечку
Порядок строгий: сначала отозвать или отключить ключ, потом смотреть историю расходов, потом выпускать новый. Обновите secret store и перезапустите только зависимые процессы — полный редеплой не нужен.
Удаление строки из Git ничего не чинит: значение живёт в истории, форках и артефактах. Скомпрометированный ключ считается мёртвым с момента подозрения, даже если источник утечки уже удалён.
Лимиты как страховка
Spend limit — единственная защита, которая работает, пока вы спите. Даже щедрый лимит лучше его отсутствия: злоумышленник упрётся в потолок, а вы получите время на ротацию.
После инцидента первым делом понизьте лимиты тестовым ключам. Второй шаг — разобраться, как ключ утёк, иначе новый постигнет та же участь.
- spend limit на каждом ключе до запуска
- уведомления об аномальном расходе
- регулярный просмотр истории по ключам
Чеклист перед продакшеном
Прогоните этот список перед первым боевым запросом. Каждый невыполненный пункт — это инцидент, отложенный во времени.
- .env в .gitignore с первого коммита
- секрет только на сервере
- логи без Authorization, промптов и ответов
- spend limit задан
- известен владелец каждого ключа
- план ротации, а не импровизация
Открыть эту статью в Markdown·Поделиться в Telegram
Следующий материалОшибки AI API: что делать с 401, 402, 429 и 503