Короткий ответ
Сканирование делают многоступенчатым: строгая блокировка (fail build) на Critical-уязвимостях с доступным патчем в слоях, контролируемых командой, и отдельный, более мягкий контроль (отчёт/тикет, но не блокировка) для унаследованных проблем базового образа с планом обновления и дедлайном.
Как это работает подробнее
уязвимости в образе делятся по происхождению — в коде/зависимостях приложения (контролирует команда напрямую) и в слоях базового образа (контролирует владелец базового образа или требует его обновления). Блокировка пайплайна эффективна только там, где команда может сразу исправить проблему; для унаследованных уязвимостей жёсткая блокировка просто останавливает всю разработку без возможности быстро исправить.
Пример кода
security-example-457.txt
# Multi-stage build уменьшает итоговую поверхность уязвимостей:
# инструменты сборки остаются в builder-слое и не попадают в финальный образ
FROM golang:1.22 AS builder
WORKDIR /src
COPY . .
RUN go build -o app .
FROM gcr.io/distroless/base-debian12
COPY --from=builder /src/app /app
ENTRYPOINT ["/app"]Что использовать на практике
- Практика. вводят политику исключений с обязательным тикетом и сроком («эта CVE в базовом образе допускается до даты X, после — блокирует релиз»), регулярно обновляют базовый образ отдельным процессом (dependabot/renovate для Dockerfile), проверяют, действительно ли уязвимый компонент базового образа используется приложением (можно исключить ненужные пакеты через multi-stage build или distroless).
- Проверка. Ожидаемое поведение: сканирование финального образа на базе distroless находит заметно меньше уязвимостей, чем сканирование builder-образа, поскольку компиляторы, пакетные менеджеры и shell отсутствуют в runtime-слое — сравнение вывода trivy image для обоих слоёв подтверждает уменьшение количества найденных CVE.
Подводные камни
- Ошибка. включать жёсткую блокировку сразу для всех найденных уязвимостей без разделения по источнику, что останавливает работу команды из-за проблем, не зависящих от неё; никогда не пересматривать список исключений, превращая временную меру в постоянную дырку в безопасности; не обновлять базовый образ месяцами, накапливая долг уязвимостей.