Оглавление
Executive summary
Если нужна короткая рекомендация, то она такая: Trivy — лучший кандидат на роль «основного сканера по умолчанию» в DevSecOps-пайплайне, потому что он объединяет проверку уязвимостей, misconfigurations, secrets, licenses, контейнерных образов, файловых систем, репозиториев и Kubernetes; Grype — очень сильный и более сфокусированный сканер именно уязвимостей и SBOM, удобный как второй независимый контроль или как сканер «по SBOM first»; OpenVAS/GVM — это уже не инструмент для build-time образов, а полноценная платформа сетевого и хостового сканирования, особенно полезная для серверов, сервисов, диапазонов адресов и аутентифицированных проверок в staging/production. На практике самые устойчивые процессы выглядят так: Trivy или Grype запускаются до merge и до релиза, чтобы ловить уязвимости в image/fs/SBOM на этапе сборки, а OpenVAS/GVM работает после деплоя или по расписанию, чтобы проверять реальные открытые сервисы, reachability, а также проводить authenticated scans с Local Security Checks. Это не взаимоисключающие инструменты, а скорее два слоя защиты: package/image-level и network/ runtime-level. С точки зрения выбора политики я бы рекомендовал такой базовый стандарт: в CI блокировать merge/release по fixable High/Critical, хранить JSON/SARIF как артефакты, использовать ignore/ VEX только с явным обоснованием и сроком пересмотра, а для внешних и критичных серверов обязательно дополнять container/image scanning сетевым сканированием OpenVAS. У Trivy есть встроенные механизмы ignore и server mode, у Grype — --fail-on , --only-fixed , ignore rules и VEX, а у GitHub/GitLab есть штатные механизмы для блокировки merge по статусам pipeline/checks.
Готовы перейти на современную серверную инфраструктуру?
В King Servers мы предлагаем серверы как на AMD EPYC, так и на Intel Xeon, с гибкими конфигурациями под любые задачи — от виртуализации и веб-хостинга до S3-хранилищ и кластеров хранения данных.
- S3-совместимое хранилище для резервных копий
- Панель управления, API, масштабируемость
- Поддержку 24/7 и помощь в выборе конфигурации
Результат регистрации
...
Создайте аккаунт
Быстрая регистрация для доступа к инфраструктуре
Сравнение инструментов
Важно не путать термины. OpenVAS сегодня — это прежде всего OpenVAS Scanner внутри более широкой платформы Greenbone Community Edition с gvmd и GSA; исторически проект был известен как OpenVAS, а Greenbone продолжает развивать и Community, и Enterprise-линейку. Источники уязвимостей и лицензия CI/CD и автоматизация Профиль ресурсов, производительность, ограничения По умолчанию требует сеть для БД, но поддерживает self-hosting БД, air- gap и offline-scan; cache backend бывает fs , memory , redis ; Есть trivy- action , client/ server mode, shared cache/ Redis, SARIF/JSON, GitHub/GitLab/ server mode убирает Jenkins повторную загрузку интегрируется БД на каждом очень runner’е; часть естественно Kubernetes/Podman/ containerd сценариев помечена как experimental Single binary без внешних зависимостей; matchers работают параллельно; БД автообновляется при запуске; отдельного сетевого/серверного сканирования нет, а cpe-match в результатах требует Есть anchore/ scan-action , --fail-on , -- only-fixed , ignore rules, VEX, SARIF/JSON/ CycloneDX; очень удобен для строгих gates по ручной severity/fix-state верификации; старые версии перестают получать обновления БД Инструмент Основное назначение
Установка и запуск Trivy и Grype
Официальные материалы Trivy покрывают image/tar/rootfs/filesystem/Podman/registry/Kubernetes- сценарии, а у Grype официально поддерживаются images из Docker/Podman/Containerd/registry, директории, файлы, архивы, SBOM и даже PURL/CPE. Ниже — практический набор команд, собранный из этих официальных возможностей и их примеров. Установка Trivy и базовая подготовка БД
В этом разделе удобно держать две вещи: (1) минимальные команды, которые реально нужны в работе, и (2) короткое объяснение, что именно вы сканируете (image / fs / SBOM) и где это уместно в CI.
# Linux/macOS
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
# прогреть БД заранее
trivy image --download-db-only
Логика простая: в CI вы сначала прогреваете базу уязвимостей, чтобы сократить время пайплайна, а потом запускаете скан по тому target, который вам нужен (image, filesystem, rootfs или Kubernetes).
# локальный Docker image
trivy image python:3.12-slim
# только уязвимости, без secrets
trivy image --scanners vuln --severity HIGH,CRITICAL python:3.12-slim
# приватный registry (лучше через login)
cat ~/registry-password.txt | trivy registry login --username "$REGISTRY_USER" --password-stdin ghcr.io
trivy image ghcr.io/acme/private-app:2026.05.08
# tar archive из docker save
docker save python:3.12-slim -o python-3.12-slim.tar
trivy image --input python-3.12-slim.tar
# проект / локальная файловая система
trivy fs .
# rootfs (например, экспортированного контейнера)
CID="$(docker create python:3.12-slim)"
mkdir -p /tmp/rootfs-app
docker export "$CID" | tar -C /tmp/rootfs-app -xvf -
trivy rootfs /tmp/rootfs-app
# Kubernetes cluster
trivy k8s --report summary
trivy k8s --kubeconfig ~/.kube/config --report all --severity CRITICAL,HIGH
Отдельный нюанс: у Trivy есть порядок источников образов (Docker Engine → containerd → Podman → registry). Его можно контролировать параметром `--image-src`, а часть Podman/Kubernetes сценариев в документации помечена как experimental.
# Linux/macOS
curl -sSfL https://get.anchore.io/grype | sudo sh -s -- -b /usr/local/bin
# базовый image scan
grype alpine:latest
# предзагрузка/обновление БД
grype db check
grype db update
Grype — single binary и “SBOM-first” подход: в CI часто удобнее сначала сгенерировать SBOM и сканировать именно его, чтобы результаты меньше зависели от окружения.
# локальный image из Docker daemon
grype docker:alpine:latest
# direct registry pull, без container runtime
grype registry:ghcr.io/acme/private-app:2026.05.08
# docker save archive
grype docker-archive:./python-3.12-slim.tar
# OCI archive / OCI dir
grype oci-archive:./image.tar
grype oci-dir:/path/to/oci-layout
# локальная директория / файловая система
grype dir:/srv/app
# SBOM
grype sbom:./sbom.cdx.json
grype ./sbom.spdx.json
# runtime-обходной вариант: экспортировать FS контейнера и сканировать как dir
CID="$(docker ps --filter name=myapp -q | head -1)"
mkdir -p /tmp/rootfs-myapp
docker export "$CID" | tar -C /tmp/rootfs-myapp -xvf -
grype dir:/tmp/rootfs-myapp
Главная идея: держите кодовые листинги отдельными блоками, а объяснения — текстом. Тогда читателю понятно, где команда, а где смысл, и в статье не появляется «розовая простыня» из PDF.

Развёртывание и запуск OpenVAS GVM
Для Greenbone/OpenVAS есть две практичные точки входа: Community Containers и пакеты Kali Linux. Greenbone прямо пишет, что container guide ориентирован на знакомство и тестирование, а не на production; при этом минимальные требования для community containers задокументированы как 2 CPU / 4 GB RAM / 20 GB свободного диска, рекомендованные — 4 CPU / 8 GB / 60 GB. Вариант через Greenbone Community Containers export DOWNLOAD_DIR="$HOME/greenbone-community-container" mkdir -p "$DOWNLOAD_DIR"
OpenVAS/GVM — это уже post‑deploy слой: он показывает, что реально доступно по сети и что уязвимо на хостах. Поэтому его обычно запускают по расписанию или после релиза, а не на каждом коммите.
export DOWNLOAD_DIR="$HOME/greenbone-community-container"
mkdir -p "$DOWNLOAD_DIR"
# скачать compose-файл
curl -f -O -L https://greenbone.github.io/docs/latest/_static/compose.yaml --output-dir "$DOWNLOAD_DIR"
# загрузить образы и поднять стек
docker compose -f "$DOWNLOAD_DIR/compose.yaml" pull
docker compose -f "$DOWNLOAD_DIR/compose.yaml" up -d
# посмотреть логи
docker compose -f "$DOWNLOAD_DIR/compose.yaml" logs -f
# обязательно сменить admin password
docker compose -f "$DOWNLOAD_DIR/compose.yaml" exec -u gvmd gvmd gvmd --user=admin --new-password='STRONG_PASSWORD'
После первого старта дождитесь завершения загрузки VT/feed. Это главный источник “почему результатов мало”. До окончания загрузки отчёты могут быть неполными или ошибочными.
# обновление/синхронизация feed data containers
docker compose -f "$DOWNLOAD_DIR/compose.yaml" pull \
notus-data vulnerability-tests scap-data dfn-cert-data cert-bund-data \
report-formats data-objects
docker compose -f "$DOWNLOAD_DIR/compose.yaml" up -d \
notus-data vulnerability-tests scap-data dfn-cert-data cert-bund-data \
report-formats data-objects
# если в compose добавлен greenbone-feed-sync — точечная ручная синхронизация
for t in nasl notus scap cert gvmd-data; do
docker compose -f "$DOWNLOAD_DIR/compose.yaml" run --rm greenbone-feed-sync greenbone-feed-sync --type "$t"
done
Feed состоит из нескольких частей (VT, SCAP/CVE/CPE, CERT, gvmd-data). Для корректного сканирования все части должны быть синхронизированы и загружены демонами.
sudo apt update
sudo apt install gvm
sudo gvm-setup
gvm-check-setup
# после gvm-setup зайдите в web UI на localhost с credential, которые выведет setup
Для автоматизации Greenbone рекомендует gvm-tools (GMP/OSP) — можно управлять через socket/TLS/SSH. В контейнерном варианте gvm-tools обычно уже есть в составе стека.
# зайти в контейнер gvm-tools
docker compose -f "$DOWNLOAD_DIR/compose.yaml" run --rm gvm-tools
# проверить gvmd
gvm-cli --gmp-username admin socket --pretty --xml ""
export IPADDRESS="192.0.2.10"\n\n# создать target\n\ngvm-cli socket --xml "Suspect Host ${IPADDRESS} "\n\n# создать task с Full and Fast\n# UUID из примера Greenbone:\n# scan config: daba56c8-73ec-11df-a475-002264764cea\n# scanner: 08b69003-5fc2-4037-a479-93b440211c73\n\ngvm-cli socket --xml "Scan Suspect Host "\n\n# запустить task\n\ngvm-cli socket --xml ""\n\n# мониторить status/progress\n\ngvm-cli socket --xml ""\n\n# получить report\n\ngvm-cli socket --xml ""

Политики и интеграция в CI CD
Сильная модель выглядит так: Trivy/Grype — в build-time и merge-time, OpenVAS/GVM — в post- deploy и по расписанию. GitHub позволяет требовать passing status checks перед merge в protected branches, а GitLab — MR pipelines с CI_PIPELINE_SOURCE == "merge_request_event" и блокировку merge через Pipelines must succeed или Status checks must succeed. Jenkins, в свою очередь, может либо проваливать build сразу, либо возвращать exit code через returnStatus и принимать решение в Pipeline-логике. timeline title Процесс сканирования в CI/CD Checkout : Получение кода Build : Сборка образа и артефактов SBOM : Опциональная генерация SBOM Scan : Trivy или Grype проверяют image, fs, sbom Policy : severity, fix-state, ignore, VEX, exit-code Publish : JSON или SARIF как артефакты Gate : Required status checks или Pipelines must succeed Remediate : Обновление зависимостей, base image и повторный прогон GitHub Actions с Trivy
Ниже — рабочие шаблоны для CI/CD. Идея простая: сканы должны быть обязательными статусами для merge/release, а отчёты (JSON/SARIF) — артефактами пайплайна.
GitHub Actions: Trivy (SARIF + gate)
name: trivy-image-scan
on:
pull_request:
jobs:
trivy:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- name: Run Trivy
uses: aquasecurity/trivy-action@v0.36.0
with:
image-ref: ghcr.io/acme/app:${{ github.sha }}
format: sarif
output: trivy-results.sarif
severity: HIGH,CRITICAL
ignore-unfixed: true
exit-code: 1
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: trivy-results.sarif
Если нужна блокировка merge — сделайте job обязательным статусом в branch protection rules. Это надёжнее, чем пытаться “проверить текст отчёта” внутри шага.
GitHub Actions: Grype (Anchore scan-action)
name: grype-scan
on:
pull_request:
jobs:
grype:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- name: Build image
run: docker build . -t localbuild/testimage:latest
- name: Scan with Grype
id: scan
uses: anchore/scan-action@v7
with:
image: localbuild/testimage:latest
fail-build: true
severity-cutoff: high
only-fixed: true
cache-db: true
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: ${{ steps.scan.outputs.sarif }}
GitLab CI: merge request pipelines + gates
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
when: never
- if: $CI_COMMIT_BRANCH
stages: [scan, postdeploy]
trivy_scan:
stage: scan
image: alpine:3.20
before_script:
- apk add --no-cache curl
- curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
script:
- trivy fs . --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1
allow_failure: false
grype_scan:
stage: scan
image: alpine:3.20
before_script:
- apk add --no-cache curl
- curl -sSfL https://get.anchore.io/grype | sh -s -- -b /usr/local/bin
script:
- grype dir:. --fail-on high --only-fixed
allow_failure: false
openvas_postdeploy:
stage: postdeploy
script:
- gvm-cli --gmp-username "$GVM_USER" --gmp-password "$GVM_PASSWORD" tls --hostname "$GVM_HOST" --xml ""
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Jenkins: declarative pipeline (идея)
pipeline {
agent any
stages {
stage('Trivy') {
steps {
sh 'curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin'
sh 'trivy fs . --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 -f json -o trivy.json'
}
}
stage('Grype') {
steps {
sh 'curl -sSfL https://get.anchore.io/grype | sh -s -- -b /usr/local/bin'
script {
int rc = sh(script: 'grype dir:. --fail-on high --only-fixed -o json > grype.json', returnStatus: true)
if (rc != 0) { error('Grype policy failed') }
}
}
}
stage('OpenVAS post-deploy') {
steps {
script {
int rc = sh(script: 'gvm-cli --gmp-username "$GVM_USER" --gmp-password "$GVM_PASSWORD" tls --hostname "$GVM_HOST" --xml ""', returnStatus: true)
if (rc != 0) { error('OpenVAS task trigger failed') }
}
}
}
}
post {
always {
archiveArtifacts artifacts: 'trivy.json,grype.json', allowEmptyArchive: true
}
}
}
Практический совет: secrets (registry creds / GVM creds) не должны попадать в MR pipelines от форков. В GitLab используйте protected variables/runners, а в GitHub — минимальные permissions и отдельные окружения.

Интерпретация результатов и ремедиация
Ключевая ошибка команд — относиться к любому CVE как к равнозначному. Так делать нельзя.
При разборе отчётов главная ошибка — считать любой CVE одинаковым. Для приоритизации важны fixability, reachability, confidence матчинга и факт эксплуатации в реальном мире (KEV).
Trivy для OS‑пакетов опирается на advisory от вендора, чтобы корректно учитывать backports. Поэтому в triage смотрите не только CVE‑ID, но и источник данных/дистрибутивную ветку.
Grype полезно читать по двум вещам: он ранжирует по risk score, а в JSON есть match type. `exact-direct-match` и `exact-indirect-match` обычно надёжнее, а `cpe-match` стоит перепроверять.
Для общей шкалы CVSS можно помнить пороги: Critical 9.0–10.0, High 7.0–8.9, Medium 4.0–6.9, Low 0.1–3.9. Но выше всего поднимайте уязвимости из KEV (Known Exploited) и findings на реально reachable сервисах (OpenVAS).

Практический порядок приоритизации
Fixable High/Critical, которые ломают policy gate — чинить первыми (в CI: Trivy `--ignore-unfixed`, Grype `--only-fixed`).
KEV / known exploited — поднимать выше обычного severity backlog.
Internet‑facing / externally reachable findings из OpenVAS — ускорять даже при равном CVSS.
High‑confidence package matches и authenticated LSC findings — лечить быстрее, чем спорные совпадения.
`cpe-match` и спорные попадания — сначала верифицировать, затем эскалировать.
# 1) обновить base image / OS packages
# 2) обновить application dependencies
# 3) пересобрать артефакт
# 4) прогнать scan повторно (Trivy/Grype)
# 5) для runtime — повторить OpenVAS по расписанию или после релиза
Безопасность, приватность и типичные ошибки
С точки зрения приватности и сетевой изоляции у трёх решений очень разный профиль. Trivy в нормальном режиме требует интернет-доступ для БД и некоторых внешних ресурсов, но поддерживает air-gapped сценарии, self-hosting БД и ручное наполнение локального cache directory; если среда ограничена по сети, --offline-scan отключает попытки API-запросов для dependency identification там, где это применимо. Кроме того, в client/server mode сам DB lives on server, а misconfig/secret scanning остаётся на клиенте, чтобы не отправлять чувствительные файлы на сервер. Для приватных registry у Trivy безопаснее использовать trivy registry login , потому что credential кладётся в Docker config ( ~/.docker/config.json , путь можно поменять через DOCKER_CONFIG ). Передача TRIVY_USERNAME / TRIVY_PASSWORD прямо в scan-команду работает, но документация отдельно предупреждает, что такие credentials могут пытаться использоваться для всех registry, с которыми Trivy сталкивается при сканировании. У Grype приватные registry тоже завязаны на Docker config и credential helpers, если используется registry: source; при наличии container runtime он может делегировать аутентификацию рантайму. Для изолированных сред важно, что Grype умеет db import , а архитектура его DB прямо допускает mirror/air-gap модели. Для GitLab MR pipelines это означает ещё одно правило: не раздавайте secrets всем pipeline’ам от форков. GitLab отдельно документирует, что доступ к protected variables и protected runners в merge request pipelines ограничивается условиями по защищённым веткам и принадлежности веток одному проекту. Это особенно важно, если в pipeline есть registry credentials или управление внешним OpenVAS. У OpenVAS/GVM главный приватный риск — это не облако и не registry, а сами authenticated scans: Greenbone пишет, что appliance логинится на target для запуска LSC, а эти логины, вероятно, будут записаны в target-system logs. Поэтому production-аккаунты для сканирования должны быть выделенными, минимально достаточными и ротационными. Самые частые проблемы я бы свёл в такую таблицу: Симптом Вероятная причина Что делать