API key injection: что это и как работает
«Injection» — это просто подстановка настоящего ключа в исходящий запрос. Вопрос не в том, происходит она или нет — она происходит всегда, у любого, кто ходит в стороннее API. Вопрос — где именно и кто это делает.
Injection — это не технология, это момент
У любого запроса к OpenAI, Stripe или Telegram Bot API есть момент, когда настоящий ключ попадает в заголовок или URL исходящего HTTP-запроса. Это и есть инжекция. По умолчанию она происходит в коде вашего приложения — вы буквально пишете headers={"Authorization": f"Bearer {api_key}"}. Ключ при этом живёт в памяти процесса, в переменных окружения, иногда — в аргументах командной строки, которые видны через ps aux любому пользователю на той же машине.
Идея credential proxy — перенести этот момент из приложения на отдельный сервер, которому вы доверяете единственную задачу: подставлять ключ. Приложение больше не видит настоящее значение вообще — оно работает с отзываемым токеном, а инжекция происходит на прокси, в последний момент перед отправкой запроса провайдеру.
Где технически происходит подстановка
| Способ | Где живёт настоящий ключ | Что видит потребитель |
|---|---|---|
| В коде приложения (классика) | В памяти процесса, в .env, в конфиге | Настоящий ключ целиком |
| Правило в nginx/Lua | В конфиге сервера или переменной окружения контейнера | Ничего — но один и тот же ключ для всех, кто достучался |
| Самодельный middleware | В БД или секретнице, которую вы поддерживаете сами | Зависит от реализации — обычно без ревокации и лимитов на потребителя |
| Credential proxy (proxykey) | Зашифровано (AES-256-GCM), расшифровка только в памяти на время одного запроса | Отзываемый токен (vlt_…), свой на каждого потребителя |
Форматы, в которые нужно уметь подставлять
Провайдеры кладут ключ в разные места запроса, и прокси, который умеет инжектировать только Authorization: Bearer, не закроет и половины реальных интеграций:
- Bearer-заголовок — самый частый случай: OpenAI, Anthropic, большинство REST API.
Authorization: Bearer sk-… - Произвольный заголовок — например,
X-Api-Keyу части провайдеров, где Bearer не используется. - Query-параметр — ключ в строке запроса,
?api_key=…. Встречается у более старых или простых API. - Путь URL — крайний случай: у Telegram Bot API токен бота — часть самого пути (
/bot<token>/sendMessage), заголовков там просто нет.
proxykey поддерживает все четыре формата на уровне конфигурации провайдера (bearer / header / query / path) — включая специальный разбор пути для Telegram, где токен извлекается прямо из URL, а не из заголовка.
Почему самодельная инжекция обычно хуже готового прокси
Технически подмену заголовка можно реализовать за один вечер в nginx или простом middleware. Разница всплывает не в момент запуска, а в момент инцидента:
| Самодельная инжекция | Credential proxy | |
|---|---|---|
| Токен на каждого потребителя | Обычно нет — один ключ на всех | Да, свой отзываемый токен |
| Отзыв доступа одному потребителю | Нужно менять конфиг и перезагружать сервис | Один клик, остальные не затронуты |
| Лимиты запросов на потребителя | Обычно не реализовано | rpm/rpd на каждый токен |
| Лог, кто и когда ходил | Нужно настраивать отдельно | Есть из коробки |
| Ключ в истории git/конфигов | Часто — конфиг сервера тоже версионируется | Ключ никогда не покидает шифрованное хранилище |
Самодельная инжекция закрывает ровно одну проблему — «ключ не в клиентском коде». Она не решает проблему, что этот же ключ по-прежнему один на всех потребителей, без права на отзыв конкретного из них.
Частые вопросы
Чем injection отличается от credential proxy?
Injection — сама операция подстановки. Credential proxy — сервис, который делает эту операцию правильно: хранит ключ зашифрованным, выдаёт потребителям отзываемые токены и логирует каждую подстановку.
Можно ли сделать инжекцию в существующем nginx?
Технически да, через proxy_set_header с секретом из защищённого хранилища. Но это статическая подмена одного и того же ключа всем, кто достучался до сервера — без отдельного токена на потребителя, без отзыва без перезагрузки конфига, без лимитов и лога по потребителю.
Работает ли инжекция со стримингом?
Да, если прокси не буферизует тело. Подмена происходит в заголовках или пути до того, как запрос уходит к провайдеру, — стриминговый ответ (SSE, чанки) идёт насквозь без изменений.
Попробуйте на одном ключе
Заведите ключ, получите проходку и переключите один сервис — это займёт минуту. Бесплатно, без карты.
Начать →