The post has been translated automatically. Original language: Russian
.env is convenient for local development, but by itself it does not make secrets secure.
The API key may accidentally end up in Git, Docker image, CI/CD logs, backup, or even a screenshot from a work chat. One failed commit, and suddenly the whole team has a small corporate quest "who will manage to reissue the key before the attacker".
For a production environment, it is better to use separate secret management systems, restrict access, and regularly rotate keys.
And the main thing is to consider the secret compromised immediately after entering the public repository. Deleting a line from the last commit is not enough, Git remembers everything. Sometimes even better than humans.
.env удобен для локальной разработки, но сам по себе он не делает секреты безопасными.
Это всего лишь способ вынести чувствительные значения из кода: API-ключи, пароли, токены, строки подключения к БД. Проблема в том, что разработчик довольно быстро начинает воспринимать .env как некий защищённый контейнер. А это обычный текстовый файл, который умеет примерно ничего в плане безопасности.
API-ключ может случайно попасть в Git, Docker image, CI/CD-логи, backup, артефакты сборки или даже скриншот из рабочего чата. Достаточно одного неудачного commit, и у команды внезапно появляется маленький корпоративный квест: кто быстрее обнаружит утечку, отключит старый ключ и перевыпустит новый раньше, чем им воспользуется кто-то ещё.
Отдельная проблема — Docker. Если секрет передавался во время сборки неаккуратно, он может остаться внутри одного из слоёв image. Даже если потом удалить файл или переменную, данные всё ещё могут жить в истории слоёв. Примерно как плохие архитектурные решения: визуально их уже нет, но последствия продолжают существовать.
С CI/CD ситуация похожая. Секреты могут попасть в логи через debug-вывод, stack trace, команды shell или неправильно настроенные pipeline. Поэтому недостаточно просто хранить значение в переменной окружения. Нужно ещё понимать, кто имеет к ней доступ, где она используется и может ли система случайно её вывести.
Для production-среды лучше использовать отдельные системы управления секретами: HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, Google Secret Manager, Kubernetes Secrets в связке с дополнительным шифрованием или аналогичные решения.
Они позволяют централизованно управлять секретами, выдавать доступ только нужным сервисам, вести аудит обращений, ограничивать срок жизни credentials и автоматизировать ротацию ключей.
Хорошая практика — минимальные привилегии. Если сервису нужен доступ только на чтение к одному API, ему не нужен универсальный токен администратора на всю инфраструктуру. Чем меньше прав у конкретного секрета, тем меньше потенциальный ущерб в случае его утечки.
То же касается срока жизни ключей. Секрет, созданный три года назад и забытый в конфигурации сервиса, — не стабильность. Это технический долг с элементами азартной игры. Ключи и токены нужно регулярно ротировать, а по возможности использовать короткоживущие credentials.
Отдельное правило — никогда не передавать реальные production-секреты разработчикам просто ради удобства. Для локальной среды лучше иметь отдельные тестовые ключи с ограниченными правами и отдельными ресурсами.
И самое главное: если секрет попал в публичный репозиторий, нужно сразу считать его скомпрометированным.
Недостаточно удалить строку из последнего commit и сделать вид, что ничего не произошло. Git хранит историю, fork репозитория мог уже появиться, автоматические боты постоянно сканируют GitHub на предмет открытых ключей, а поисковые системы и кэши тоже существуют.
Правильная реакция выглядит так: немедленно отозвать или перевыпустить секрет, проверить логи его использования, оценить потенциальный ущерб и только потом чистить историю репозитория.
Потому что .env — это удобство конфигурации, а не система безопасности.
А Git действительно помнит всё. Иногда даже лучше людей.