Короткий ответ
Git хранит полную историю, поэтому секрет, попавший в коммит, остаётся доступным даже после удаления файла; секреты нужно передавать через переменные окружения, менеджер секретов или volume, а не хардкодить в исходный код.
Как это работает подробнее
Git — система с полной историей изменений; удаление строки в новом коммите не удаляет её из истории, секрет можно найти через git log/git blame или просто скачав архив репозитория. Любой, у кого есть доступ к репозиторию (включая форки, CI-логи, бэкапы), получает секрет.
Пример кода
security-example-441.sh
# секрет случайно закоммичен
cat .env
DB_PASSWORD=SuperSecret123
git log --oneline -- .env
a1b2c3d add .env with db config
git show a1b2c3d:.env
DB_PASSWORD=SuperSecret123Что использовать на практике
- Практика. секреты передают через переменные окружения, монтируемые файлы/volume или через специализированные системы (Vault, AWS Secrets Manager, Kubernetes Secret), которые разделяют доступ к конфигурации и доступ к значению секрета. Для публичных и приватных репозиториев одинаково важно включить сканирование на секреты (gitleaks, git-secrets) в CI.
- Проверка. Ожидаемое поведение: даже после удаления .env новым коммитом и git rm .env, старый коммит a1b2c3d всё ещё содержит пароль — его можно получить командой git show. Единственное надёжное исправление — ротация пароля и очистка истории (git filter-repo), а не просто новый коммит.
Подводные камни
- Ошибка. считать приватный репозиторий безопасным хранилищем секретов; добавлять
.envс реальными значениями в git; забывать, что для секрета, попавшего в историю, нужна ротация, а не просто удаление файла.