Сканирование уязвимостей контейнерных образов
Updated Jul 2026
Почему сканирование контейнеров обязательно
Контейнерные образы накапливают уязвимости по трём направлениям: базовые образы поставляются с CVE уровня ОС, установленные пакеты привносят уязвимости уровня приложений, а зависимости приложений тянут за собой транзитивные риски. Один непроверенный образ может содержать десятки известных эксплойтов.
Ключевой вывод: сканирование должно происходить на этапе сборки, а не после развёртывания. Уязвимость, обнаруженная в продакшене, означает, что ваша поверхность атаки уже была раскрыта. Уязвимость, пойманная в CI, означает, что она никогда не попала в кластер.
Три вектора сканирования
| Вектор | Пример | Метод обнаружения |
|---|---|---|
| Пакеты ОС | CVE OpenSSL в базовом образе | Сканирование слоёв образа (Trivy, Grype) |
| Языковые зависимости | Уязвимый пакет npm/pip/gem | Анализ SBOM + база уведомлений |
| Ошибки конфигурации | Запуск от root, открытые порты | Линтинг Dockerfile (Trivy config, Hadolint) |
Комплексная стратегия сканирования покрывает все три направления. Большинство команд начинают со сканирования образов и добавляют сканирование конфигурации по мере роста зрелости.
Trivy: швейцарский нож
Trivy (от Aqua Security) — наиболее универсальный сканер с открытым исходным кодом. Он обрабатывает образы, файловые системы, Git-репозитории и кластеры Kubernetes одним бинарным файлом.
Базовое сканирование
# Scan a local image for vulnerabilities
trivy image --severity HIGH,CRITICAL myapp:latest
# Scan and fail CI if critical vulnerabilities are found
trivy image --exit-code 1 --severity CRITICAL myapp:latest
# Scan a Dockerfile for misconfigurations
trivy config --severity HIGH,CRITICAL ./Dockerfile
# Scan a filesystem (catches vulnerabilities in source code dependencies)
trivy filesystem --severity HIGH,CRITICAL .
# Generate an SBOM (Software Bill of Materials)
trivy image --format spdx-json -o sbom.json myapp:latest
Trivy в CI/CD
# .github/workflows/container-scan.yml
name: Container Security Scan
on:
push:
paths:
- 'Dockerfile*'
- 'package*.json'
- 'requirements*.txt'
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build image
run: docker build -t myapp:${{ github.sha }} .
- name: Scan for vulnerabilities
uses: aquasecurity/trivy-action@master
with:
image-ref: myapp:${{ github.sha }}
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'HIGH,CRITICAL'
exit-code: '1'
- name: Upload scan results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: 'trivy-results.sarif'
- name: Scan Dockerfile for misconfigurations
uses: aquasecurity/trivy-action@master
with:
scan-type: 'config'
scan-ref: '.'
severity: 'HIGH,CRITICAL'
Игнорирование ложных срабатываний
Не каждая CVE эксплуатируема в вашем контексте. Trivy поддерживает файл .trivyignore:
# .trivyignore
# CVE-2024-1234: Not exploitable because we don't use the affected function
CVE-2024-1234
# Temporary ignore until upstream fix is released (expires 2026-03-01)
# CVE-2025-5678: Waiting for Node.js 22.3 patch
CVE-2025-5678
Всегда документируйте, почему вы игнорируете CVE. Недокументированные исключения накапливаются в скрытый риск.
Grype: сканер уязвимостей от Anchore
Grype — ещё один популярный сканер из экосистемы Anchore. Он хорошо сочетается с Syft (генератор SBOM от Anchore):
# Scan a local image
grype myapp:latest --fail-on high
# Scan from an SBOM (faster for repeated scans)
syft myapp:latest -o json > sbom.json
grype sbom:sbom.json --fail-on critical
# Output in table format for human review
grype myapp:latest --output table
# Output in SARIF for CI integration
grype myapp:latest --output sarif > grype-results.sarif
Сравнение Grype и Trivy
| Функция | Trivy | Grype |
|---|---|---|
| Базы уязвимостей | NVD, специфичные для ОС и языков | NVD, специфичные для ОС и языков |
| Сканирование Dockerfile | Да (режим config) | Нет (только образы) |
| Сканирование кластера K8s | Да | Нет (используйте Anchore Enterprise) |
| Генерация SBOM | Встроенная | Отдельный инструмент (Syft) |
| Скорость | Быстро | Быстро |
| Уровень ложных срабатываний | Низкий | Низкий |
| Механизм исключений | Файл .trivyignore |
Конфигурация .grype.yaml |
Многие команды используют оба инструмента и сравнивают результаты. Разные сканеры используют разные базы уведомлений и могут обнаруживать разные CVE.
Snyk Container: коммерческое решение с рекомендациями по исправлению
Snyk отличается тем, что предоставляет рекомендации по исправлению — он сообщает, какое обновление базового образа или версия пакета устранит уязвимость:
# Scan with fix recommendations
snyk container test myapp:latest --severity-threshold=high
# Monitor continuously (alerts on new CVEs for deployed images)
snyk container monitor myapp:latest
# Get base image upgrade recommendations
snyk container test myapp:latest --file=Dockerfile
# Output includes:
# Tested 1 image, found 12 vulnerabilities
# Base Image Vulnerabilities Severity
# node:20 42 8 critical, 15 high
#
# Recommendations:
# Minor upgrade: node:20.11 (removes 8 vulnerabilities)
# Alternative: node:20-slim (removes 30 vulnerabilities)
# Best: node:20-alpine (removes 38 vulnerabilities)
Сканирование реестра: непрерывная защита
Сканирование на этапе сборки необходимо, но недостаточно. Новые CVE раскрываются ежедневно, и образ, который был чистым вчера, может оказаться уязвимым сегодня. Сканирование реестра выявляет этот дрифт.
Стратегии сканирования
| Стратегия | Когда | Инструмент |
|---|---|---|
| Сканирование при сборке | Каждая сборка CI | Trivy, Grype, Snyk |
| Сканирование реестра | Ежедневно / при push | Harbor, ECR scanning, Trivy operator |
| Сканирование в рантайме | Непрерывно | Falco, Sysdig, Aqua |
| Аудит SBOM | При раскрытии новой CVE | Grype против сохранённых SBOM |
Сканирование AWS ECR
# Enable enhanced scanning on ECR repository
aws ecr put-image-scanning-configuration \
--repository-name myapp \
--image-scanning-configuration scanOnPush=true
# Check scan results
aws ecr describe-image-scan-findings \
--repository-name myapp \
--image-id imageDigest=sha256:abc123
Сканирование в реестре Harbor
# Harbor automatically scans on push and can block vulnerable images
# Configuration in Harbor UI or API:
# - Scan on push: enabled
# - Prevent vulnerable images from running:
# severity threshold: High
# - Auto-scan schedule: daily at 02:00 UTC
Построение пайплайна сканирования
Рекомендуемый подход — многоуровневое сканирование на нескольких этапах:
Машина разработчика CI-пайплайн Реестр Рантайм
| | | |
|-- Hadolint |-- Сборка образа |-- Скан при push |-- Falco
| (линт Dockerfile) |-- Скан Trivy |-- Ежедневный | (обнаружение
| |-- Скан Grype | повторный | аномалий)
|-- docker scan |-- Fail при CRITICAL | скан |
| (быстрая локальная |-- Генерация SBOM |-- Блокировка |
| проверка) |-- Загрузка в реестр | pull уязв. |
| | | образов |
Пример CI-этапа
#!/bin/bash
# scripts/scan-container.sh
set -euo pipefail
IMAGE="$1"
SEVERITY_THRESHOLD="${2:-HIGH}"
echo "=== Scanning $IMAGE ==="
# Stage 1: Dockerfile lint
echo "--- Hadolint ---"
hadolint Dockerfile --failure-threshold warning
# Stage 2: Image vulnerability scan
echo "--- Trivy ---"
trivy image --exit-code 1 --severity "$SEVERITY_THRESHOLD" "$IMAGE"
# Stage 3: SBOM generation
echo "--- SBOM ---"
trivy image --format spdx-json -o "sbom-$(date +%Y%m%d).json" "$IMAGE"
# Stage 4: Cross-reference with Grype
echo "--- Grype ---"
grype "$IMAGE" --fail-on high
echo "=== All scans passed ==="
Этот многоуровневый подход гарантирует, что даже если один сканер пропустит CVE, другой её обнаружит. SBOM обеспечивает аудиторский след для будущих раскрытий уязвимостей.