Безопасность контейнеров веб-приложения: что ревьюить
Контейнер может запускаться без root и всё равно раскрыть данные: например, если в образ попал токен или приложению открыли лишний сетевой доступ. Разбираем, что проверять в Dockerfile, образе и Kubernetes-манифестах.

Контейнер веб-приложения может работать без root и всё равно дать атакующему путь к секретам или соседним сервисам: достаточно скопировать токен в образ, смонтировать лишнюю директорию или выдать поду широкие права. На ревью проверяйте не одну настройку, а путь от исходного кода до запущенного процесса. Ниже — чек-лист для Docker-образов и Kubernetes workload-манифестов; точные названия полей и допустимые настройки сверяйте с версиями платформы в вашем проекте.
Сначала зафиксируйте границы ревью
Этот разбор относится к OCI-образам, Dockerfile и приложениям, запускаемым в Kubernetes. Он не заменяет аудит кластера, облачного аккаунта и сетевой инфраструктуры. Для конкретных проверок ниже ориентир — Docker Engine 27.x и Kubernetes 1.30: это обозначение целевых версий, а не рекомендация считать их актуальными или обновлять без проверки совместимости.
Попросите автора показать не только Dockerfile, но и то, что реально собирается и разворачивается: настройки CI, итоговый образ, манифесты Deployment или Job, конфигурацию секретов и права сервисного аккаунта. Dockerfile задаёт намерение, но CI может собрать другой тег, а манифест — запустить образ с другими полномочиями.
Проверяйте цепочку, а не отдельные строки
1. Содержимое и происхождение образа
Спросите, откуда берётся базовый образ, кто его обновляет и как команда узнаёт об уязвимостях. В Dockerfile настораживают незафиксированный тег вроде latest и образ из неизвестного реестра. Но закреплённый тег сам по себе не гарантирует неизменность содержимого; для воспроизводимой сборки проверьте, использует ли команда digest и как обновляет базовый образ.
Уточните, что попало в конечный слой: исходники, тестовые инструменты, дампы базы, файлы локальной разработки. Многоступенчатая сборка помогает не переносить компилятор и зависимости сборки в runtime-образ, но не удаляет секрет, если тот уже записался в слой на предыдущем шаге.
Попросите показать результат сканирования именно того образа, который отправляется в реестр, и правило принятия решения: какие находки блокируют релиз, кто принимает исключение и когда его пересматривают. Сам факт запуска сканера ещё не означает, что критичная уязвимость остановит деплой.
2. Секреты и сборочный контекст
В истории изменений ищите пароли, приватные ключи, токены и резервные копии с данными. Не ограничивайтесь текущим Dockerfile: секрет мог попасть в слой, кэш сборки, артефакт CI или уже опубликованный образ. Если учётные данные раскрылись, удаление строки из репозитория недостаточно — секрет нужно отозвать и выпустить заново.
Проверьте файл исключений из сборочного контекста: в него обычно убирают локальные настройки, каталоги репозитория и временные файлы. Затем проверьте, откуда приложение получает секреты в рабочей среде. Значение не должно попадать в образ, открытый лог или диагностическую страницу; доступ к хранилищу секретов должен соответствовать реальным потребностям приложения.
3. Пользователь, права и доступ к хосту
В runtime-процессе проверьте, что приложение не работает от root без обоснованной необходимости. Одной директивы в Dockerfile недостаточно: настройки запуска или платформы могут изменить пользователя. Посмотрите итоговую конфигурацию и проверьте фактический UID процесса после старта.
В Kubernetes обратите внимание на запуск с повышенными привилегиями, добавленные Linux capabilities, режим hostPID или hostNetwork и доступ к устройствам хоста. Для веб-приложения такие исключения требуют конкретного объяснения. Проверяйте также монтирования: каталог с сокетом Docker или чувствительной частью файловой системы хоста превращает компрометацию приложения в гораздо более серьёзный инцидент.
Сверьте запросы приложения с правами service account. Если контейнеру не нужно обращаться к Kubernetes API, проверьте, отключено ли автоматическое предоставление токена там, где это поддерживается политикой кластера. Если API нужен, выясните, какие именно операции и ресурсы доступны. Широкая роль «на всякий случай» повышает ущерб от уязвимости в приложении.
4. Сеть и границы доверия
Проверьте, какие порты открывает процесс, кто может обращаться к нему и куда он сам может подключаться. В Kubernetes NetworkPolicy имеет смысл только при сетевом плагине, который применяет такие политики. Наличие манифеста без проверки фактического поведения не доказывает, что трафик ограничен.
Сопоставьте сетевые правила с функциями приложения: внешний веб-трафик, соединение с базой данных, очередью и сервисом авторизации. Если поду доступна вся внутренняя сеть, компрометация веб-слоя может превратиться в доступ к системам, которым приложение не должно доверять.
Сводка: что проверять и чем рискуете
| Зона | Что запросить на ревью | Что может пойти не так |
|---|---|---|
| Образ | Источник, фиксирование версии, отчёт сканирования, состав runtime-образа | Уязвимые зависимости или случайно включённые данные |
| Секреты | Источники значений, исключения сборочного контекста, правила ротации | Утечка токена через образ, CI или журнал |
| Права | Пользователь процесса, привилегии, capabilities, service account | Выход за границы приложения при его компрометации |
| Сеть и тома | Порты, сетевые политики, подключения, монтирования | Доступ к соседним сервисам или хосту |
| Релиз | Связь сканирования с блокировкой деплоя и исключениями | Уязвимый образ выпускается несмотря на предупреждение |
Хорошее ревью отвечает не на вопрос «есть ли у нас сканер», а на вопрос «какой ущерб возможен, если этот контейнер уже скомпрометирован».
Формулировки замечаний, которые помогают исправить риск
Замечание вроде «усильте безопасность контейнера» не задаёт ни результата, ни критерия проверки. Привязывайте его к конкретной настройке, сценарию и ожидаемому изменению. Например:
- «В образ копируется файл локальной конфигурации, в котором могут быть учётные данные. Исключите его из сборочного контекста и проверьте, что его содержимого нет в итоговом образе».
- «Приложение запускается с привилегиями root, хотя доступ к устройствам хоста не нужен. Запустите процесс от отдельного непривилегированного пользователя и проверьте права на каталоги, куда приложение пишет».
- «Service account имеет права на ресурсы, которые приложение не использует. Ограничьте доступ необходимыми операциями и проверьте права в тестовом окружении».
- «Сканирование сообщает об уязвимости, но релиз не блокируется. Зафиксируйте порог блокировки, процедуру исключения и срок повторной проверки».
Не превращайте замечания в универсальный запрет. Например, запуск от root может быть временно нужен для конкретной операции при старте, а доступ к Kubernetes API — частью архитектуры. В таком случае ревью должно выяснить, можно ли вынести действие в отдельный компонент и как ограничить его полномочия, а не принять исключение без срока и владельца.
Граничные случаи: где чек-лист даёт ложное чувство безопасности
Отсутствие критических находок в сканере не доказывает безопасность приложения: инструмент может не увидеть ошибку авторизации, небезопасную логику или секрет, переданный только во время запуска. Чистый образ тоже не защищает от чрезмерных прав в манифесте. Проверки должны дополнять друг друга.
Отдельно смотрите на временные окружения, миграции и фоновые задачи. Им часто дают те же права, что основному веб-сервису, хотя их поведение и риск отличаются. Если приложение пишет в файловую систему, проверьте, что произойдёт при заполнении временного хранилища и перезапуске пода; ограничение записи может повысить безопасность, но сломать загрузку файлов или работу кэша.
Для устойчивого контроля сохраните результаты сканирования с привязкой к digest образа, а не только к имени тега. В эксплуатации наблюдайте за отказами запуска, изменениями прав и сетевыми отклонениями. Придумывать универсальный порог по числу уязвимостей нельзя: он зависит от среды, доступности исправления и того, достижим ли уязвимый компонент из вашего приложения.
Digest — криптографический идентификатор содержимого образа. В отличие от изменяемого тега он помогает точно указать, какой именно образ проверяли и развернули.
Что делать дальше
Возьмите один образ веб-приложения и пройдите цепочку целиком: Dockerfile, контекст сборки, итоговый образ, настройки запуска, service account и сетевые правила. Для каждого найденного риска запишите сценарий ущерба, владельца исправления и проверку, которая подтвердит результат. Затем повторите ревью для фонового worker и миграций: одинаковый исходный код не означает одинаковые права или поверхность атаки.
Материал описывает практику ревью контейнеризированных приложений, а не полный аудит безопасности Kubernetes-кластера. Для версий платформы и поддерживаемых настроек сверяйтесь с документацией именно той версии, которую эксплуатируете.
Редактор изображений: Убрать лишнее, заменить фон, добавить объект, расширить кадр — на вашем изображении.
Спросить за 20 ₽Источники: Docker Docs: Building best practices, Kubernetes: Security Checklist
Частые вопросы
Достаточно ли добавить USER в Dockerfile?
Если сканер образа ничего не нашёл, контейнер безопасен?
Что делать, если токен уже попал в образ?
Как поступить, если у меня другая версия Docker или Kubernetes?
Какие ошибки особенно опасны в проде?
Нужно ли блокировать каждый релиз из-за уязвимости в образе?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.