.env крайне удобен, и почти каждый современный фреймворк его использует. Но положите его не туда хоть раз — и все секреты в нём сможет прочитать кто угодно. Разберём, что это и как его защитить, с нуля.
Чуть подробнее
У приложений есть «значения, меняющиеся от окружения к окружению» и «значения, которые никто не должен видеть»: пароль БД, внешние ключи API, ключ, шифрующий сеансы. Зашейте их в исходный код — и секреты утекут в тот момент, когда вы поделитесь кодом.
Поэтому вы собираете их в один файл .env и читаете из кода как «переменные окружения». Next.js, Laravel, Rails и многие фреймворки работают так.
Содержимое — обычный текст, по одной паре ИМЯ=значение в строке (значения ниже — заглушки).
APP_ENV=production
DB_HOST=127.0.0.1
DB_PASSWORD=your-db-password-here
PAYMENT_API_KEY=your-payment-api-key-hereХранить конфигурацию вне кода популяризировало руководство по проектированию веб-приложений «The Twelve-Factor App». Его проверка того, правильно ли отделена конфигурация, — можно ли в любой момент сделать код открытым, не скомпрометировав ни одних учётных данных. .env — удобный контейнер для этой идеи при разработке.
Чем он отличается от похожих вещей
Вот что чаще всего путают с .env. Безопасным местом для секретов является лишь часть из них.
| Название | Что это | Можно ли хранить секреты? |
|---|---|---|
| Переменные окружения | Значения, которые ОС или контейнер передаёт работающему процессу | Да (норма в продакшене) |
.env | Переменные окружения, собранные в файл | Да, но никогда в публичном каталоге или Git |
.env.example | Образец со списком имён и пустыми значениями | Нет (он предназначен для коммита) |
NEXT_PUBLIC_* / VITE_* | Переменные, встраиваемые в JavaScript для браузера | Нет (их может прочитать кто угодно) |
| Менеджер секретов | Облачный сервис для хранения секретных значений | Да; управляется правами и журналами аудита |
Четвёртую строку и упускают. Next.js при сборке встраивает значения переменных, начинающихся с NEXT_PUBLIC_, а Vite — с VITE_, в JavaScript, отправляемый в браузер. Даже если такая переменная лежит в .env, с одним из этих префиксов она становится публичной.
Почему это «самый опасный файл»
Поскольку несколько ключей лежат в одном файле, единственное раскрытие быстро разносит ущерб. Перечисление «что разблокирует каждое утёкшее значение» делает серьёзность наглядной.
| Утёкшее значение | Что происходит |
|---|---|
| Учётные данные БД | чтение / изменение / стирание данных |
| Внешние ключи API | использование от чужого имени, мошеннические списания |
Ключ шифрования (например, Laravel APP_KEY, ключи подписи) | подделка сеанса, вход от чужого имени |
| Секреты OAuth | захват связанных приложений |
И правда, раскрытие .env — классический инцидент. → .env, открытый всему миру
Реальные случаи: раскрытые .env становятся целью
- Масштабная операция вымогательства (2024): исследовательская группа компании в области безопасности сообщила об активности, которая охватила 110 000 доменов, собирала раскрытые на веб-серверах файлы
.env, использовала облачные учётные данные из них, чтобы забирать данные, и требовала выкуп. Было собрано более 90 000 переменных, около 7000 из них — для облачных сервисов и около 1500 — для аккаунтов в соцсетях. Причиной была не уязвимость облачного провайдера, а ошибки настройки у организаций, раскрывших свои.env - Vercel (апрель 2026 г.): несанкционированный доступ к внутренним системам привёл к тому, что были прочитаны переменные окружения части клиентов — хранившиеся в категории, значения которой можно отобразить повторно → подробный разбор (на английском)
- Публичные репозитории (исследование 2026 г.): более 540 000 учётных данных, опубликованных на GitHub, на момент исследования всё ещё действовали. Удаление файла или истории не помогает, если учётные данные не отозваны → подробный разбор
Первый случай показывает, что раскрытые .env находят не люди, листающие сайты, — их собирают автоматически и массово. Не думайте, что небольшой сайт не найдут.
Типичная утечка = ошибка размещения
Главная причина — «класть всё приложение в публичную директорию (docroot)». Там, где обслуживаться должен только public/, раскрытие его родительской папки делает .env тоже достижимым.
✗ Опасно (приложение в публичном корне)
public_html/ ├─ .env ← читается! ├─ app/ └─ public/
✓ Безопасно (приложение снаружи, обслуживается только public)
app-root/ ├─ .env ← недостижим ├─ app/ └─ public_html/ → public/
Помимо размещения, он утекает и такими путями:
- Коммит в Git (в публичном репозитории — мгновенно публичен; в приватном — виден всем, у кого есть доступ)
- Резервные копии вроде
.env.bakили.env.old, оставленные в публичном каталоге - Образ контейнера или zip-дистрибутив, в котором остался
.env - Секреты в переменных
NEXT_PUBLIC_/VITE_, как описано выше
Как его защитить
Не кладите его в публичную директорию
Держите приложение вне docroot; обслуживайте только public/. Конкретные шаги для шаред-хостинга: это руководство.
Не коммитьте его в git
Добавьте .env* в .gitignore и делитесь только .env.example с пустыми значениями.
Ротируйте всё, если он утёк
Не только подтверждённый ключ — замените каждый ключ, что был в .env. Действуйте так, будто видели все.
Регулярно делайте самопроверку
Выработайте привычку проверять, что /.env нельзя открыть на вашем собственном сайте.
Как проверить сайт и репозиторий
Самопроверка (только против доменов, которыми вы владеете)
# 200 с телом означает, что он раскрыт. 403/404 — пока в порядке.
curl -sI https://yourdomain/.env | head -1
curl -sI https://yourdomain/.git/config | head -1Проверка этого при каждом деплое рано ловит ошибки размещения.
Проверяйте и снаружи сайта, и внутри репозитория.
- Для сайта, владение которым вы подтвердили, аудит безопасности сайта разом проверяет
/.env,/.env.local,/.env.bakи похожие пути - В репозитории выполните
git log --all --oneline -- .env, чтобы увидеть, коммитился ли он когда-либо. Если что-то нашлось, отзовите ключи, которые в нём были - Вставьте конфигурацию или код в сканер утечек секретов, чтобы найти зашитые ключи API или закрытые ключи (он работает в вашем браузере)
- Просмотрите список переменных
NEXT_PUBLIC_/VITE_, чтобы ни один секрет не попал в собранный JavaScript
Мнение этого сайта: решайте вместе, где лежит .env и как отзывать его ключи
Большинство инцидентов с .env начинается с одного файла не в том месте. А разрастается ущерб потом из-за того, что нет готовой процедуры замены ключей. На этом сайте мы рекомендуем: если вы используете .env, не только держите его вне публичного каталога и Git, но и заранее запишите, как отозвать и перевыпустить каждый ключ в нём. В продакшене переход на облачный менеджер секретов или на переменные окружения, значения которых нельзя отобразить повторно, ещё сильнее сокращает пути утечки.
Источники (первичные)
- The Twelve-Factor App, «III. Config» — 12factor.net (хранить конфигурацию в переменных окружения; проверка «можно ли открыть код»)
- Документация Next.js, «Environment Variables» — nextjs.org (
NEXT_PUBLIC_встраивается в JavaScript при сборке; не коммитить файлы .env) - Документация Vite, «Env Variables and Modes» — vite.dev (переменные
VITE_доступны клиентскому коду) - Unit 42 (Palo Alto Networks), «Leaked Environment Variables Allow Large-Scale Extortion Operation in Cloud Environments» (15 августа 2024 г.) — unit42.paloaltonetworks.com