Trivy: проверка образов Docker на уязвимости, секреты и ошибки Dockerfile

Образ контейнера состоит из системных пакетов и библиотек, и в старом образе уязвимостей обычно сотни. Проверять каждый образ вручную невозможно, поэтому нужен сканер в конвейере. Trivy проверяет образы на известные уязвимости, ищет секреты и разбирает Dockerfile на типовые ошибки. Ниже порядок работы и результаты проверки на тестовом образе.
Статья опирается на логику направления «Управление уязвимостями» из методики зрелости Группы Сбер (источник); это методика для крупных компаний, мы используем её как ориентир и пересказываем своими словами. Проверка выполнена с Trivy 0.75.0, запущенным в контейнере; тестовые образы и кэш после неё удалены.
Что должно получиться
| Уровень | Что это значит на практике |
|---|---|
| 2. Гигиенический | Образы проверяются при каждой сборке и по расписанию, уязвимости с доступным исправлением закрываются в согласованные сроки |
Критерии сформулированы нами по мотивам методики, это ориентир, а не оценка соответствия.
Тестовый образ
Возьмём старый образ с двумя намеренными ошибками: запуск от root и секрет в переменной окружения (значение из документации AWS, не настоящее):
FROM python:3.9-slim
COPY app.py /app/app.py
ENV AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
CMD ["python", "/app/app.py"]
Запуск Trivy в контейнере с доступом к локальным образам:
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
-v trivy-cache:/root/.cache/ aquasec/trivy:0.75.0 image --scanners vuln ИМЯ_ОБРАЗА
Ключ -v trivy-cache:/root/.cache/ сохраняет базу уязвимостей между запусками: без него она скачивается заново каждый раз. Версию Trivy фиксируйте тегом, а не latest.
Результат проверки
| Проверка | Результат на тестовом образе |
|---|---|
| Уязвимости, все уровни | 466 находок: 6 критических, 113 высоких, 188 средних, 156 низких, 3 без оценки. Основная часть в системных пакетах (Debian) и в pip и setuptools |
| Из них с готовым исправлением | 6 критических и 69 высоких; остальные исправления пока нет |
| Порог CI: HIGH и CRITICAL с исправлением | 72 в системных пакетах (66 высоких и 6 критических) и ещё 3 высоких в пакетах Python |
| Секреты в слоях образа | Ничего не найдено: этот ключ из документации сканер секретов в слоях не отметил, а запись в ENV выявила проверка Dockerfile |
| Ошибки Dockerfile | 3 находки: DS-0031 (критическая) секрет в ENV, DS-0002 (высокая) нет пользователя без прав root, DS-0026 (низкая) нет HEALTHCHECK |
Секрет в файле (fs) |
Случайный токен формата GitHub PAT в файле leak.env найден как критический: файл и строка указаны |
Новый образ (python:3.13-slim, пользователь без прав root) |
Только 4 высоких уязвимости с исправлением (вместо 75) |
Вывод: самая эффективная мера — обновление базового образа. Сканер без обновления даёт длинный список, который никто не разберёт.
Пороги и скрипт для конвейера
Проверка по всем находкам останавливает сборки бесконечно. Практичный порог: HIGH и CRITICAL, для которых уже есть исправленная версия (--ignore-unfixed). Скрипт:
#!/usr/bin/env bash
# Проверка образа на известные уязвимости: падает при находках HIGH и CRITICAL, у которых уже есть исправление.
set -u
IMAGE="${1:?укажите образ, например myapp:1.0}"
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v trivy-cache:/root/.cache/ \
aquasec/trivy:0.75.0 image --scanners vuln --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 "$IMAGE"
rc=$?
case $rc in
0) echo "trivy: HIGH/CRITICAL с доступным исправлением не найдено" ;;
1) echo "trivy: есть уязвимости с исправлением, сборку нужно остановить" ;;
*) echo "trivy: ошибка запуска (код $rc)" ;;
esac
exit $rc
Коды возврата: 0 — порог не превышен, 1 — есть находки (задаётся ключом --exit-code 1), другие значения — ошибка запуска. Без --exit-code Trivy всегда возвращает 0, и сборка не остановится, даже если находки есть. В тесте скрипт вернул 1.
Секреты и ошибки Dockerfile
Для файлов проекта и Dockerfile используются другие режимы:
trivy fs --scanners secret ПУТЬ # секреты в файлах
trivy config ПУТЬ # ошибки Dockerfile и конфигураций
Важная ловушка: trivy config . внутри контейнера без подключённого каталога ничего не проверяет (в отчёте прочерки), поэтому каталог проекта нужно смонтировать (-v $PWD:/src) и проверять /src. Секрет, найденный в репозитории, считайте скомпрометированным: смените его, а не просто удалите файл (секреты в git).
Порядок внедрения
- Составьте список образов, которые реально запущены, и их владельцев.
- Просканируйте все без порога и сохраните результат как исходное состояние.
- Обновите базовые образы до поддерживаемых версий: это убирает основную часть находок.
- Включите порог в CI: HIGH и CRITICAL с доступным исправлением.
- Запускайте проверку по расписанию и для уже развёрнутых образов: новые уязвимости появляются без изменения вашего кода.
- Исправьте Dockerfile: пользователь без прав root, без секретов в ENV, безопасный запуск контейнеров.
- Оформите исключения (файл
.trivyignoreс кодом уязвимости, причиной и сроком пересмотра) и сроки закрытия по общему процессу.
Диагностика
| Симптом | Причина и что делать |
|---|---|
| Сканирование долго качает базу | Нет постоянного кэша. Подключите том для /root/.cache/ |
| Сборка не останавливается при находках | Не задан --exit-code 1. Добавьте ключ |
| Тысячи находок в старом образе | Устаревший базовый образ. Обновите его, затем включайте порог |
| Находка есть, исправления нет | Используйте --ignore-unfixed для порога, но следите за такими записями в отчёте и закрывайте после выхода обновления |
trivy config показывает прочерки |
Проверяемый каталог не смонтирован в контейнер. Смонтируйте и укажите путь внутри контейнера |
| Секрет в ENV не найден сканером секретов | В тесте запись ENV выявила проверка config (правило DS-0031), а не поиск секретов по слоям; запускайте обе проверки |
| Ложные срабатывания | Добавьте запись в .trivyignore с причиной и сроком пересмотра |
Ограничения
Trivy находит только известные уязвимости и не видит ошибок логики приложения и неверной настройки сервисов внутри контейнера. Он также не заменяет анализ собственного кода и проверку зависимостей приложения. Отсутствие находок означает «в базе на сегодня ничего нет», а не «образ безопасен».
Где это в модели зрелости
Материал относится к направлению «Управление уязвимостями» (материалы направления, карта зрелости). Уровень 2 требует процесса с приоритетами и сроками: автоматическая проверка образов добавляет к сканированию серверов контейнерную часть инфраструктуры.
Как проверить
- Есть список запущенных образов с владельцами и датой последней проверки.
- Trivy запускается в конвейере, версия закреплена, сборка останавливается на пороге.
- Образ с известной критической уязвимостью, для которой есть исправление, не проходит сборку.
- Образы работают от пользователя без прав root, секретов в ENV и слоях нет.
- Исключения оформлены записью с причиной и сроком пересмотра.
Источники
- Методика оценки уровня зрелости кибербезопасности компании, Группа Сбер: sberbank.ru.
- Документация Trivy: trivy.dev; исходный код: github.com/aquasecurity/trivy.
- OWASP Top 10: A06 Vulnerable and Outdated Components: owasp.org. Международная практика, не российский норматив.






















