Отделите публичные настройки от секретов
Составьте список используемых значений без самих секретов: назначение, поставщик, владелец, окружение, разрешённые операции и способ замены. Адрес API и публичный идентификатор проекта не всегда являются секретом. Пароль базы, ключ подписи, токен управления ботом и ключ платного сервиса требуют другого обращения.
В Supabase publishable/anon-ключ рассчитан на публичную часть в сочетании с корректными правами и RLS. Secret/service_role-ключ даёт повышенный доступ и предназначен для доверенной серверной части. Само присутствие публичного ключа в странице не доказывает утечку; проверяйте тип ключа и доступ, который реально получают клиентские роли.
Подробнее в первоисточнике: Supabase: публичные и серверные API-ключи.
Почему .env и .gitignore недостаточно
Файл .env — способ передать настройки процессу, а не универсальное хранилище секретов. Значение может попасть в сборку, если приложение специально отправляет его клиенту. Vite публикует доступные клиентскому коду переменные с префиксом VITE_; серверный секрет туда не помещают. Проверяйте правила своего фреймворка и итоговую сборку.
Исключение из новых коммитов не удаляет уже опубликованную историю. Ключ также может находиться в архиве релиза, логе ошибки, скриншоте или сообщении агента. Учебный пример: разработчик убрал ключ из исходника, но старый JavaScript продолжает раздаваться хостингом. Исправление должно охватывать источник и опубликованный результат.
- В клиентской сборке должны находиться только значения, которые допустимо отдать посетителю.
- Пример конфигурации содержит названия и описание переменных, но не действующие ключи.
- Журнал запроса не сохраняет секреты из заголовков или строк подключения.
- Инструментам разработки выдаются только нужные доступы; секреты не копируются в публичные задачи и отчёты.
Подробнее в первоисточнике: Vite: переменные окружения в клиентской сборке; GitHub: действия при публикации секрета.
Если ключ уже опубликован
GitHub рекомендует начинать устранение утечки секрета с отзыва или ротации. Удаление сообщения и переписывание истории сами по себе не делают сохранённую посторонним копию недействительной. Порядок замены зависит от поставщика и возможности временно держать два ключа.
Остановите источник повторной публикации до размещения нового значения. Если есть признаки использования ключа посторонним, прекращение этого доступа важнее бесшовной замены; согласуйте остановку затронутой интеграции с её владельцем. Не оставляйте старое значение активным только ради красивого статуса «сервис работает».
- Определите, какой именно доступ раскрыт, и сохраните время обнаружения и место публикации без дополнительного распространения ключа.
- Исправьте источник утечки и отзовите раскрытый доступ либо выполните предусмотренную поставщиком ротацию.
- Обновите все разрешённые потребители: приложение, фоновые задачи, интеграции и окружения.
- Проверьте безопасной операцией, что новый ключ работает, а прежний больше не даёт доступ.
- Разберите журналы и расход за возможный период утечки; отсутствие записей не доказывает, что использования не было.
- Удалите доступные копии из публикаций и артефактов, затем устраните причину и сохраните результаты разбора.
Подробнее в первоисточнике: GitHub: действия при публикации секрета; OWASP: хранение, права и жизненный цикл секретов.
Ограничьте последствия следующей ошибки
В учебном сервисе отчётов задача чтения каталога не должна использовать тот же доступ, который удаляет всю базу. Разделяйте назначение ключей и окружения, назначайте минимальные нужные права и владельца. Это позволяет заменить одну интеграцию, не раздавая всем полный доступ к системе.
Проверьте процедуру замены на тестовом ключе до инцидента. Обновление только веб-процесса легко пропускает фонового обработчика или старый сервер. Полезен список потребителей и подтверждение каждого из них, а не поиск «похожих строк» после отказа рабочих задач.
| Что записать | Зачем |
|---|---|
| Название и назначение ключа | Понимать, какая операция перестанет работать при отзыве. |
| Права и окружение | Оценивать доступ и не переносить рабочие полномочия в тест. |
| Потребители | Обновить приложение, задачи и интеграции полностью. |
| Владелец и способ отзыва | Не искать доступ к кабинету поставщика во время инцидента. |
| Результат проверки старого ключа | Подтвердить прекращение раскрытого доступа. |
Что может и чего не может HTTP-защита
Правила публичного сервера и дополнительный фильтр могут ограничивать обращения к служебным путям на подключённом домене. Но сначала уберите секреты из раздаваемых файлов: блокировка одного имени .env не закрывает копии под другими именами, в сборке или архиве.
RoboGuard не отзывает ключи Telegram, облака, базы или платёжного провайдера. Если ключ используется напрямую в API поставщика, этот запрос не проходит через домен вашего приложения. Подключение WAF полезно для HTTP-трафика, но не является способом сделать опубликованный токен снова секретным.
Вопросы и ответы
Ключ удалён из последнего коммита. Этого достаточно?
Нет, если действующее значение уже стало доступно посторонним. Нужен отзыв или ротация у поставщика и проверка, что старый доступ закрыт; затем устраняются доступные копии и источник утечки.
Любая строка API key в браузере — уязвимость?
Нет. Некоторые платформы используют публичные ключи. Сначала выясните их назначение, права и ограничения по документации поставщика. Серверный секрет нельзя считать публичным только потому, что приложение с ним работает.