Пошук уроків, статей та іншого контенту
Перевірите образи за допомогою сканерів, розберете CVE та налаштуєте контроль вразливостей у CI.
Docker-образ містить не лише код застосунку, а й:
базову операційну систему;
системні пакети;
бібліотеки мов програмування;
залежності застосунку;
службові утиліти.
У кожному з цих компонентів можуть бути відомі вразливості. Навіть якщо власний код не містить проблем, уразлива версія бібліотеки або пакета може зробити небезпечним увесь контейнер.
Сканер образів:
аналізує шари образу;
визначає встановлені пакети та їхні версії;
порівнює їх із базою відомих вразливостей;
показує знайдені CVE;
за потреби завершує процес із помилкою, щоб не пропустити небезпечний образ у CI.
Сканування не доводить, що образ повністю безпечний. Воно виявляє відомі проблеми в компонентах, які можна ідентифікувати.
CVE — це ідентифікатор публічно відомої вразливості. Він має формат на кшталт:
CVE-2024-XXXXЗвіт сканера зазвичай містить:
ідентифікатор CVE;
пакет, у якому знайдено проблему;
встановлену версію;
виправлену версію;
рівень небезпеки;
тип компонента — операційна система чи бібліотека;
джерело вразливості.
Рівень небезпеки часто визначається за шкалою CVSS:
LOW — низький;
MEDIUM — середній;
HIGH — високий;
CRITICAL — критичний.
Рівень небезпеки допомагає розставити пріоритети, але не замінює аналіз контексту. Наприклад, вразливість мережевого сервера може бути значно важливішою для публічного образу, ніж така сама оцінка для пакета, який не використовується під час роботи застосунку.
Створимо простий образ на основі Alpine Linux.
Dockerfile:
FROM alpine:3.20
RUN apk add --no-cache curl
CMD ["curl", "--version"]Побудуємо образ:
docker build -t security-demo:1.0 .Переконаємося, що образ існує локально:
docker image ls security-demoДля реального проєкту образ зазвичай має складніший набір залежностей, тому результати сканування будуть кориснішими на власному застосунку.
Trivy — сканер, який уміє перевіряти Docker-образи на відомі вразливості операційної системи та бібліотек.
Після встановлення Trivy виконайте:
trivy image security-demo:1.0Сканер завантажить або оновить локальну базу вразливостей і покаже звіт.
Для перевірки лише серйозних проблем використовуйте параметр --severity:
trivy image \
--severity HIGH,CRITICAL \
security-demo:1.0У цьому випадку у звіті залишаться лише вразливості рівнів HIGH і CRITICAL.
Іноді база містить вразливість, для якої ще немає оновленої версії пакета. Такі записи називають unfixed.
Щоб не показувати їх у звіті:
trivy image \
--severity HIGH,CRITICAL \
--ignore-unfixed \
security-demo:1.0Це зменшує кількість шуму, але приховує інформацію про відомі проблеми без доступного виправлення. Для повного аудиту краще не використовувати --ignore-unfixed.
За замовчуванням Trivy може показати вразливості, але все одно завершити процес успішно. Для CI потрібно зробити так, щоб небезпечний результат зупиняв конвеєр:
trivy image \
--severity HIGH,CRITICAL \
--ignore-unfixed \
--exit-code 1 \
security-demo:1.0Параметр --exit-code 1 означає:
код 0 — вразливості заданих рівнів не знайдено;
код 1 — знайдено хоча б одну вразливість;
інші коди можуть вказувати на помилку самого сканування.
Перевірити код завершення в оболонці можна так:
trivy image \
--severity HIGH,CRITICAL \
--ignore-unfixed \
--exit-code 1 \
security-demo:1.0
status=$?
if [ "$status" -ne 0 ]; then
echo "Сканування виявило проблеми або завершилося з помилкою"
exit "$status"
fi
echo "Критичних вразливостей не знайдено"Для локальної роботи зручний табличний формат:
trivy image \
--format table \
security-demo:1.0Для подальшої обробки програмами можна сформувати JSON:
trivy image \
--format json \
--output trivy-report.json \
security-demo:1.0JSON-звіт можна зберегти як артефакт CI або передати іншій системі аналізу.
Не слід автоматично ігнорувати кожну знайдену вразливість. Послідовність дій може бути такою:
Визначити компонент і його версію.
Перевірити, чи доступна виправлена версія.
Зрозуміти, чи використовується вразливий компонент під час роботи застосунку.
Оновити базовий образ або залежність.
Перебудувати образ без кешу, якщо це необхідно.
Повторити сканування.
Перевірити, чи вразливість зникла.
Якщо проблема походить від базового образу, спочатку можна оновити його версію:
FROM alpine:3.21
RUN apk add --no-cache curl
CMD ["curl", "--version"]Після зміни образ потрібно перебудувати:
docker build --pull --no-cache -t security-demo:1.1 .Параметри:
--pull перевіряє наявність новішої версії базового образу;
--no-cache не використовує кеш попередньої збірки.
Потім виконайте повторне сканування:
trivy image \
--severity HIGH,CRITICAL \
--ignore-unfixed \
--exit-code 1 \
security-demo:1.1Якщо вразливість належить пакету Alpine, потрібно використовувати версію пакета з виправленням. Для базового образу Alpine це зазвичай означає встановлення пакета під час збірки з актуальних репозиторіїв:
FROM alpine:3.21
RUN apk update \
&& apk upgrade \
&& apk add --no-cache curl \
&& rm -rf /var/cache/apk/*
CMD ["curl", "--version"]У багатьох випадках достатньо актуальної версії базового образу та встановлення пакетів через apk add --no-cache. Команду apk upgrade слід застосовувати усвідомлено, оскільки оновлення пакета може змінити поведінку системи.
Локальне сканування корисне, але його легко забути. Надійніший підхід — перевіряти образ у CI після кожної зміни.
Приклад кроків для CI, що підтримує shell-команди:
set -e
IMAGE="security-demo:${CI_COMMIT_SHA:-local}"
docker build --pull -t "$IMAGE" .
trivy image \
--severity HIGH,CRITICAL \
--ignore-unfixed \
--exit-code 1 \
--format table \
"$IMAGE"У цьому прикладі:
образ отримує тег із хешем коміту;
образ будується до сканування;
--pull перевіряє актуальність базового образу;
наявність виправленої вразливості рівня HIGH або CRITICAL провалює job;
образ не потрібно публікувати до реєстру, якщо він не пройшов перевірку.
Файл .github/workflows/container-security.yml:
name: Container security
on:
push:
branches:
- main
pull_request:
jobs:
scan:
runs-on: ubuntu-latest
steps:
- name: Отримати код
uses: actions/checkout@v4
- name: Побудувати Docker-образ
run: docker build --pull -t security-demo:${{ github.sha }} .
- name: Встановити Trivy
uses: aquasecurity/trivy-action@0.28.0
with:
image-ref: security-demo:${{ github.sha }}
format: table
vuln-type: os,library
severity: HIGH,CRITICAL
ignore-unfixed: true
exit-code: '1'Ключова властивість цього прикладу — exit-code: '1'. Якщо Trivy знайде вразливість вибраного рівня, job завершиться невдало, а наступні етапи CI не виконуватимуться.
У власному проєкті пороги потрібно узгодити з командою. Наприклад:
для pull request блокувати CRITICAL;
для гілки main блокувати HIGH і CRITICAL;
для MEDIUM створювати попередження або окрему задачу;
вразливості без виправлення не блокувати, але відстежувати окремо.
Потрібно заздалегідь визначити, які результати зупиняють доставку образу.
Приклад простої політики:
CRITICAL із доступним виправленням — завжди блокувати.
HIGH із доступним виправленням — блокувати для production-образів.
MEDIUM — реєструвати та виправляти за планом.
LOW — не блокувати збірку.
UNFIXED — відстежувати до появи виправлення.Політика має враховувати призначення образу. Вимоги до production-образу можуть бути суворішими, ніж до тимчасового образу для локального тестування.
Не варто без пояснення додавати CVE до ігнорування. Якщо виняток справді потрібен, зафіксуйте:
ідентифікатор вразливості;
причину винятку;
відповідального;
дату повторного перегляду;
умови, за яких виняток буде видалено.
Docker також має власний інструмент аналізу образів — Docker Scout. Для перевірки образу можна використати:
docker scout cves security-demo:1.0Щоб обмежити звіт серйозними вразливостями:
docker scout cves \
--only-severity high,critical \
security-demo:1.0Docker Scout зручний, якщо команда вже використовує Docker CLI та Docker Registry. Trivy часто обирають для незалежного локального сканування і простого запуску в різних CI-системах. Важливо не змішувати результати різних сканерів без аналізу: вони можуть використовувати різні бази, правила та способи визначення виправлених версій.
Практичний процес може виглядати так:
Розробник змінює Dockerfile або залежності.
CI будує образ із хешем коміту.
Сканер перевіряє OS-пакети та бібліотеки.
Вразливості перевіряються за погодженою політикою.
Якщо поріг перевищено, CI зупиняється.
Розробник оновлює базовий образ або залежність.
Образ сканується повторно.
Лише після успішної перевірки образ публікується або розгортається.
Після зміни Dockerfile старий образ може залишитися з тим самим тегом або використовуватися через кеш.
Перебудову можна виконати так:
docker build --pull --no-cache -t security-demo:latest .Сканування Docker-контексту та сканування образу — не одне й те саме. Уразливий пакет може з’явитися вже в базовому образі або під час встановлення системних залежностей.
Перевіряйте саме фінальний образ:
trivy image security-demo:latestВелика кількість записів у звіті не означає, що їх усі потрібно приховати. Спочатку потрібно відокремити:
виправлені та невиправлені вразливості;
пакети, які реально входять до фінального образу;
компоненти, що використовуються під час виконання;
проблеми різного рівня небезпеки.
Тег на кшталт latest може вказувати на різний вміст у різний час. Після кожного оновлення базового образу потрібно повторно запускати сканування та перевірки.
Якщо блокувати збірку через будь-яку вразливість, команда може почати масово додавати винятки. Політика повинна мати зрозумілі пороги, відповідальних і процес перегляду винятків.
Docker-образи містять операційну систему, системні пакети та залежності, у яких можуть бути CVE.
Сканер порівнює версії компонентів із базою відомих вразливостей.
Для локальної перевірки можна використовувати Trivy або Docker Scout.
Параметри --severity, --ignore-unfixed і --exit-code допомагають налаштувати поведінку перевірки.
У CI сканування потрібно виконувати після побудови образу.
Образ із критичними або високими вразливостями слід блокувати відповідно до політики команди.
Основний спосіб виправлення — оновити базовий образ або залежність і повторити сканування.
Винятки мають бути обґрунтованими, тимчасовими та контрольованими.