Trivy, Grype a Syft — vulnerability a SBOM scanning
V roku 2021 podpísal Biden Executive Order 14028, ktorý nariadil federálnym dodávateľom softvéru poskytovať Software Bill of Materials (SBOM) pre každý dodaný produkt. Európsky Cyber Resilience Act (CRA) bol adoptovaný v októbri 2024 a vstúpil do účinnosti v decembri 2024 — hlavné povinnosti (vrátane SBOM + vulnerability managementu) sa vyžadujú až od decembra 2027, reporting obligations už od septembra 2026. V 2026 teda SBOM a vulnerability scanning sú už dnes povinné pre federal USA kontrakty a pre EU trh máte posledných 18 mesiacov, aby ste boli pripravení — de-facto štandard, nie nice-to-have.
Tento článok sa zaoberá tromi nástrojmi, ktoré dnes dominujú tejto oblasti: Syft (SBOM generátor), Grype (vulnerability scanner konzumujúci SBOM) a Trivy (all-in-one Swiss Army knife pre security scanning). Vysvetlíme, kedy použiť ktorý nástroj, ukážeme reálne CI/CD workflows a povieme si aj o pastách, do ktorých tímy pravidelne padajú.
Supply chain security — kontext problému
Prečo SBOM v 2026 nie je voliteľný
Softvérové dodávateľské reťazce sa stali primárnym vektorom útokov. SolarWinds (2020), Log4Shell (2021), XZ Utils backdoor (2024) — všetky tieto incidenty mali spoločného menovateľa: organizácie nevedeli, čo presne beží v ich softvéri.
SBOM (Software Bill of Materials) je strojovo spracovateľný inventár všetkých komponentov v softvérovom produkte — knižníc, verzií, licencií, závislostí. Funguje analogicky k zoznamu ingrediencií na potravinách: keď sa objaví zraniteľnosť, viem okamžite zistiť, či môj produkt obsahuje postihnutú knižnicu.
Regulačný kontext 2026:
| Regulácia | Región | Požiadavka |
|---|---|---|
| EO 14028 | USA (federal) | SBOM pre každý dodaný softvér |
| EU CRA | EÚ | Vulnerability management + SBOM pre "important products" |
| NIST SP 800-218 | USA | SSDF — secure software development framework |
| FDA Guidance | USA (medical) | SBOM povinný pre medical device software od 2023 |
Supply chain attack surface
Developer workstation
│
▼
Source code
│ ← dependency confusion, typosquatting (npm, pip, rubygems)
▼
Build system (CI)
│ ← poisoned build tools, compromised runners
▼
Container image
│ ← malicious base image, layer injection
▼
Container registry
│ ← image tampering without attestation
▼
Production runtime
│ ← runtime exploits, zero-day v tranzitívnych závislostiach
▼
Customer
SBOM + vulnerability scanning adresuje každú vrstvu tohto reťazca — nie retrospektívne, ale kontinuálne.
SBOM formáty — CycloneDX vs SPDX
Existujú dva dominantné štandardy pre SBOM. Oba sú strojovo čitateľné, oba sú akceptované regulátormi, ale majú odlišné filozofie.
CycloneDX (OWASP)
CycloneDX vznikol v rámci OWASP projektu a je zameraný na security use-case. Verzia 1.6 (2024) pridala podporu pre attestations, SBOM for ML models a vulnerability exploitability exchange (VEX).
Podporované formáty serializácie: JSON, XML, Protocol Buffers.
Silné stránky:
- Natívna podpora pre VEX (Vulnerability Exploitability eXchange) — umožňuje publisher-om dokumentovať, prečo konkrétna CVE neovplyvňuje ich produkt
- Bohatá sémantika pre services, formulas (build recipes), attestations
- Aktívny OWASP community development
SPDX (Linux Foundation)
SPDX (Software Package Data Exchange) vznikol v Linux Foundation, pôvodne pre licenčné compliance. Verzia 3.0 (2024) pridala security profil, ale jeho primárna sila ostáva v licenčnej oblasti.
Podporované formáty: JSON, YAML, RDF, tag-value.
Silné stránky:
- ISO/IEC 5962:2021 — medzinárodný štandard
- Silná podpora pre licenčné compliance (SPDX License List)
- Preferovaný v open-source ekosystéme (Linux kernel používa SPDX)
Kedy použiť ktorý
Security scanning, VEX, supply chain attestations → CycloneDX
Licenčné compliance, open-source governance → SPDX
Potrebuješ oboje → generuj CycloneDX JSON, konvertuj cez cdxgen/sbom-utility
V praxi: väčšina security nástrojov (Grype, Trivy, Dependency-Track) preferuje CycloneDX. Ak pracuješ s právnikmi okolo licencií, pridaj aj SPDX export.
Syft — SBOM generátor od Anchore
Syft je open-source SBOM generátor od Anchore (tej istej spoločnosti, ktorá stojí za Grype). Jeho úloha je jednoduchá a dobre ohraničená: preskenovať softvérovú jednotku a vygenerovať SBOM. Sám o sebe nevyhľadáva zraniteľnosti — to prenecháva Grype.
Čo Syft skenuje
Container images → docker.io/nginx:latest, oci:// tarball, daemon://
Filesystems → adresár, tar archív
Git repozitáre → github.com/org/repo (experimentálne)
SBOM (re-index) → importuje existujúci SBOM a re-exportuje
Syft rozpoznáva balíčkové manažéry: dpkg, rpm, apk, pip/pipenv/poetry, npm/yarn/pnpm, gem, cargo, go modules, maven/gradle, nuget, conan, hex, pub a ďalšie.
Výstupné formáty
| Format | Flag | Použitie |
|---|---|---|
| CycloneDX JSON | cyclonedx-json |
Security scanning, Dependency-Track |
| CycloneDX XML | cyclonedx-xml |
Staršie enterprise tooling |
| SPDX JSON | spdx-json |
Licenčné compliance |
| SPDX tag-value | spdx-tag-value |
Jednoduchá čitateľnosť |
| Syft JSON | json |
Natívny formát, najbohatší |
| Table | table |
Terminálový výstup pre ľudí |
Inštalácia
# Binary (odporúčané pre CI)
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
# Homebrew
brew install syft
# Docker (bez inštalácie)
docker run --rm anchore/syft:latest nginx:latest
# asdf
asdf plugin add syft
asdf install syft latest
Základné použitie
# SBOM pre Docker image (CycloneDX JSON)
syft nginx:latest -o cyclonedx-json=nginx-sbom.json
# SBOM pre lokálny filesystem
syft dir:/path/to/app -o cyclonedx-json=app-sbom.json
# SBOM pre OCI tarball
syft oci-archive:image.tar -o spdx-json=image-sbom.spdx.json
# Tabular výstup (debug/quick check)
syft python:3.12-slim -o table
# Všetky formáty naraz
syft nginx:latest \
-o cyclonedx-json=sbom.cdx.json \
-o spdx-json=sbom.spdx.json \
-o json=sbom.syft.json
Syft + Cosign — podpísaný SBOM
Kľúčovým krokom v supply chain security je attestation — kryptografický dôkaz, že SBOM bol vygenerovaný konkrétnym procesom a nebol manipulovaný. Cosign (Sigstore projekt) umožňuje priložiť SBOM ako attestation priamo k OCI image.
# 1. Vygeneruj SBOM
syft my-registry.io/myapp:v1.2.3 -o cyclonedx-json=sbom.cdx.json
# 2. Podpíš SBOM ako attestation (keyless, Sigstore)
cosign attest \
--type cyclonedx \
--predicate sbom.cdx.json \
my-registry.io/myapp:v1.2.3
# 3. Verifikuj attestation
cosign verify-attestation \
--type cyclonedx \
--certificate-identity-regexp "https://github.com/org/repo/.*" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
my-registry.io/myapp:v1.2.3 | jq '.payload | @base64d | fromjson'
# 4. Stiahni a preskúmaj predicate
cosign download attestation my-registry.io/myapp:v1.2.3 \
| jq -r '.payload | @base64d | fromjson | .predicate'
Keyless signing cez Sigstore funguje tak, že Cosign si vyžiada krátkodobý certifikát od Fulcio CA pomocou OIDC tokenu (GitHub Actions identity). Tento certifikát je zalogovaný do Rekor transparency logu, čo umožňuje auditovateľnosť bez správy súkromných kľúčov.
Grype — vulnerability scanner od Anchore
Grype je companion nástroj k Syft. Zatiaľ čo Syft generuje SBOM, Grype ho konzumuje a hľadá zraniteľnosti. Môže skenovať aj priamo image/filesystem (interne používa Syft), ale jeho killer feature je SBOM-first prístup: môžeš generovať SBOM raz a scannovať opakovane bez prístupu k pôvodnému obrazu.
Databázy zraniteľností
Grype agreguje z viacerých zdrojov:
NVD — National Vulnerability Database (NIST)
OSV — Open Source Vulnerabilities (Google)
GHSA — GitHub Advisory Database
VulnDB — (komerčná licencia, voliteľná)
Distribučné:
Alpine SecDB, Debian Security Tracker,
Ubuntu CVE Tracker, RHEL/CentOS/Amazon/Oracle advisories,
Wolfi/Chainguard advisories
Databáza sa cachuje lokálne (~/.cache/grype/db/), aktualizuje pri každom spustení alebo cez grype db update.
Inštalácia
# Binary
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
# Homebrew
brew install grype
# Docker
docker run --rm anchore/grype:latest nginx:latest
Základné použitie
# Scan Docker image
grype nginx:latest
# Scan z existujúceho SBOM (kľúčová feature!)
grype sbom:nginx-sbom.json
# Scan s výstupom SARIF (pre GitHub Security)
grype nginx:latest -o sarif > grype-results.sarif
# Scan s JSON výstupom
grype nginx:latest -o json > grype-results.json
# Iba high/critical
grype nginx:latest --fail-on high
# Scan lokálneho adresára
grype dir:/path/to/app
# Ignoruj fixable (ukazuj len nevyriešiteľné)
grype nginx:latest --only-fixed
Grype konfigurácia — ignorovanie false positives
Grype konfiguráciu definuješ v .grype.yaml v root-e projektu alebo v ~/.grype.yaml:
# .grype.yaml
ignore:
# Ignoruj konkrétnu CVE pre konkrétny balíček
- vulnerability: CVE-2023-44487
package:
name: golang.org/x/net
version: "0.14.0"
# Ignoruj CVE keď nie je fix
- fix-state: not-fixed
# Ignoruj celú CVE globálne (s komentárom prečo)
- vulnerability: CVE-2023-29491 # ncurses, not exposed in container
fail-on-severity: high
output:
- format: table
- format: sarif
file: grype-results.sarif
Trivy — all-in-one security scanner od Aqua Security
Trivy je produkt Aqua Security (open-source core, komerčná Aqua Platform). Na rozdiel od Syft/Grype kombinácie je Trivy one-stop-shop: vulnerability scanning, SBOM generovanie, IaC misconfiguration detection, secrets scanning a licenčné scanning — všetko v jednom binárnom súbore.
Čo Trivy skenuje
Container images → docker.io/nginx:latest, oci-archive, podman
Filesystems → lokálny adresár, tar archív
Git repozitáre → vzdialený alebo lokálny
SBOM → CycloneDX/SPDX ako vstup
Kubernetes → live cluster (cez kubeconfig)
AWS → S3, EC2, ECS, Lambda (cloud misconfiguration)
VM images → AMI, VMDK
Helm charts → `trivy config` na Helm values
Trivy typy skenovania
| Scanner | Flag | Čo hľadá |
|---|---|---|
| Vulnerability | --scanners vuln |
CVE v OS a language packages |
| Misconfiguration | --scanners misconfig |
IaC problémy (Terraform, CFN, K8s, Dockerfile) |
| Secret | --scanners secret |
API kľúče, tokeny, heslá v kóde |
| License | --scanners license |
GPL, AGPL, riziková licencie |
| SBOM | (výstup) | Generovanie CycloneDX/SPDX |
Inštalácia
# Binary (Linux)
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
# Homebrew
brew install trivy
# Docker
docker run --rm aquasec/trivy:latest image nginx:latest
# Helm (trivy-operator)
helm repo add aqua https://aquasecurity.github.io/helm-charts/
helm repo update
helm install trivy-operator aqua/trivy-operator \
--namespace trivy-system \
--create-namespace
# APT (Debian/Ubuntu)
sudo apt-get install wget apt-transport-https gnupg lsb-release
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
echo "deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" \
| sudo tee /etc/apt/sources.list.d/trivy.list
sudo apt-get update && sudo apt-get install trivy
Základné použitie
# Vulnerability scan image
trivy image nginx:latest
# Scan s SARIF výstupom
trivy image --format sarif --output trivy-results.sarif nginx:latest
# SBOM generovanie
trivy image --format cyclonedx --output sbom.cdx.json nginx:latest
trivy image --format spdx-json --output sbom.spdx.json nginx:latest
# IaC misconfiguration scan
trivy config ./terraform/
trivy config ./k8s-manifests/
trivy config Dockerfile
# Secrets scan
trivy fs --scanners secret ./
# Kubernetes cluster scan
trivy k8s --report summary cluster
trivy k8s --namespace production --report all
# Scan s threshold (CI gate)
trivy image --exit-code 1 --severity HIGH,CRITICAL nginx:latest
# Všetky skenery naraz
trivy image \
--scanners vuln,secret,license \
--format table \
nginx:latest
Trivy IaC — porovnanie s Checkov
Trivy config scanner je priamy konkurent Checkov (Bridgecrew/Prisma). Porovnanie:
| Feature | Trivy config | Checkov |
|---|---|---|
| Terraform | ✓ | ✓ |
| CloudFormation | ✓ | ✓ |
| Kubernetes YAML | ✓ | ✓ |
| Dockerfile | ✓ | ✓ |
| Helm charts | ✓ | ✓ |
| ARM templates | ✗ | ✓ |
| Custom rules (OPA/Rego) | ✓ | ✓ |
| Custom rules (Python) | ✗ | ✓ |
| SARIF output | ✓ | ✓ |
| CI integrations | GitHub, GitLab, Jenkins | GitHub, GitLab, Jenkins, CircleCI |
Trivy config je dosť dobrý pre základné kontroly, ale Checkov má širšiu databázu pravidiel a lepšiu podporu pre custom Python checks. Ak už máš Trivy v CI pipeline, neinštaluj Checkov navyše — Trivy pokryje 80% use-casov. Pre compliance-heavy prostredie (PCI-DSS, CIS Benchmarks) zvaž Checkov alebo Terrascan.
.trivyignore — správa výnimiek
# .trivyignore
# Formát: CVE-ID [expiry-date] [comment]
# Ignoruj globálne (bez expirácie — nebezpečné!)
CVE-2023-44487
# Ignoruj s dátumom expirácie (odporúčané!)
CVE-2023-29491 exp:2026-06-01
# Ignoruj konkrétny misconfiguration check
AVD-DS-0002
# Ignoruj secret finding
generic-api-key
# Komentáre sú povolené
# CVE-2024-12345 — opravené v next sprint, ticket JIRA-456
CVE-2024-12345 exp:2026-05-15
Dôležité: každá výnimka by mala mať:
- Dátum expirácie (
exp:YYYY-MM-DD) — inak výnimka existuje navždy - Komentár s dôvodom a odkazom na ticket
- Pravidelný review (odporúčame kvartálny)
Bez expirácie sa .trivyignore stáva skládkou zabudnutých výnimiek, kde reálne zraniteľnosti žijú mesiace až roky.
Feature comparison table
| Feature | Trivy | Grype | Syft |
|---|---|---|---|
| Primárna úloha | All-in-one | Vuln scanner | SBOM generátor |
| Image scanning | ✓ | ✓ | ✓ (SBOM only) |
| Filesystem scan | ✓ | ✓ | ✓ |
| Git repo scan | ✓ | ✗ | experimentálne |
| K8s cluster scan | ✓ (native) | ✗ | ✗ |
| IaC misconfig | ✓ | ✗ | ✗ |
| Secrets detection | ✓ | ✗ | ✗ |
| License scanning | ✓ | ✗ | ✓ (v SBOM) |
| CycloneDX output | ✓ | ✓ (input+output) | ✓ |
| SPDX output | ✓ | ✓ (input+output) | ✓ |
| SBOM as input | ✓ | ✓ | ✗ |
| SARIF output | ✓ | ✓ | ✗ |
| VEX support | ✓ | ✓ | ✗ |
| NVD | ✓ | ✓ | N/A |
| OSV | ✓ | ✓ | N/A |
| GHSA | ✓ | ✓ | N/A |
| Distro advisories | ✓ | ✓ | N/A |
| GitHub Actions | ✓ (official) | ✓ (community) | ✓ (community) |
| K8s Operator | ✓ (trivy-operator) | ✗ | ✗ |
| Air-gapped support | ✓ | ✓ | ✓ |
| DB size | ~250 MB | ~150 MB | N/A |
| Scan speed | stredná | rýchla | rýchla |
| Maintainer | Aqua Security | Anchore | Anchore |
| CNCF status | nie (Aqua OSS) | nie (Anchore OSS) | nie (Anchore OSS) |
GitHub Actions workflows
Trivy — vulnerability scan + SARIF upload
# .github/workflows/trivy-scan.yml
name: Trivy Security Scan
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
# Denný scan o 02:00 UTC
- cron: '0 2 * * *'
permissions:
contents: read
security-events: write # potrebné pre SARIF upload
jobs:
trivy-image-scan:
name: Trivy Image Scan
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t ${{ github.repository }}:${{ github.sha }} .
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@0.28.0
with:
image-ref: '${{ github.repository }}:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
ignore-unfixed: true
vuln-type: 'os,library'
scanners: 'vuln,secret'
- name: Upload Trivy scan results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: 'trivy-results.sarif'
category: 'trivy-image'
trivy-iac-scan:
name: Trivy IaC Misconfiguration Scan
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run Trivy config scanner
uses: aquasecurity/trivy-action@0.28.0
with:
scan-type: 'config'
scan-ref: '.'
format: 'sarif'
output: 'trivy-config.sarif'
severity: 'CRITICAL,HIGH,MEDIUM'
- name: Upload config scan results
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: 'trivy-config.sarif'
category: 'trivy-config'
trivy-sbom:
name: Generate and Attest SBOM
runs-on: ubuntu-latest
needs: trivy-image-scan
permissions:
contents: read
id-token: write # pre keyless Cosign signing
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Generate SBOM with Trivy
uses: aquasecurity/trivy-action@0.28.0
with:
image-ref: '${{ github.repository }}:${{ github.sha }}'
format: 'cyclonedx'
output: 'sbom.cdx.json'
- name: Upload SBOM artifact
uses: actions/upload-artifact@v4
with:
name: sbom-cyclonedx
path: sbom.cdx.json
retention-days: 90
Syft — generovanie SBOM + Cosign attestation
# .github/workflows/sbom-attest.yml
name: SBOM Generation and Attestation
on:
push:
tags:
- 'v*'
permissions:
contents: read
id-token: write # pre Cosign keyless signing
packages: write # pre push do GHCR
jobs:
sbom-and-attest:
name: Build, SBOM, Attest
runs-on: ubuntu-latest
env:
IMAGE: ghcr.io/${{ github.repository }}:${{ github.ref_name }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ env.IMAGE }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Install Syft
run: |
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh \
| sh -s -- -b /usr/local/bin
- name: Install Cosign
uses: sigstore/cosign-installer@v3
- name: Generate CycloneDX SBOM
run: |
syft ${{ env.IMAGE }} \
-o cyclonedx-json=sbom.cdx.json \
-o spdx-json=sbom.spdx.json
- name: Attest SBOM with Cosign (keyless)
run: |
cosign attest \
--type cyclonedx \
--predicate sbom.cdx.json \
${{ env.IMAGE }}
- name: Upload SBOM artifacts
uses: actions/upload-artifact@v4
with:
name: sbom-${{ github.ref_name }}
path: |
sbom.cdx.json
sbom.spdx.json
retention-days: 365
scan-sbom-with-grype:
name: Scan SBOM with Grype
runs-on: ubuntu-latest
needs: sbom-and-attest
permissions:
security-events: write
steps:
- name: Download SBOM
uses: actions/download-artifact@v4
with:
name: sbom-${{ github.ref_name }}
- name: Install Grype
run: |
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh \
| sh -s -- -b /usr/local/bin
- name: Scan SBOM with Grype
run: |
grype sbom:sbom.cdx.json \
--output sarif \
--file grype-results.sarif \
--fail-on high
- name: Upload Grype SARIF to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: grype-results.sarif
category: 'grype-sbom'
Trivy Kubernetes Operator
trivy-operator je Kubernetes Operator, ktorý kontinuálne skenuje workloady v klastri a výsledky ukladá ako Kubernetes Custom Resources. Namiesto jednorazového CI scanu dostaneš live security posture celého klastra.
Inštalácia cez Helm
helm repo add aqua https://aquasecurity.github.io/helm-charts/
helm repo update
helm install trivy-operator aqua/trivy-operator \
--namespace trivy-system \
--create-namespace \
--set="trivy.ignoreUnfixed=true" \
--set="operator.scanJobTimeout=5m" \
--set="compliance.specs[0]=k8s-cis-1.27" \
--set="trivy.severity=CRITICAL\,HIGH" \
--version 0.22.0
Custom Resources, ktoré Operator vytvára
# VulnerabilityReport — pre každý pod/container
apiVersion: aquasecurity.github.io/v1alpha1
kind: VulnerabilityReport
metadata:
name: replicaset-nginx-6d8d4f5b8b-nginx
namespace: production
labels:
trivy-operator.resource.kind: ReplicaSet
trivy-operator.resource.name: nginx-6d8d4f5b8b
trivy-operator.container.name: nginx
spec:
scanner:
name: Trivy
vendor: Aqua Security
version: "0.49.0"
registry:
server: index.docker.io
artifact:
repository: library/nginx
tag: "1.25.3"
summary:
criticalCount: 0
highCount: 3
mediumCount: 12
lowCount: 45
unknownCount: 2
vulnerabilities:
- vulnerabilityID: CVE-2023-44487
resource: golang.org/x/net
installedVersion: "0.14.0"
fixedVersion: "0.17.0"
severity: HIGH
title: "HTTP/2 rapid reset attack"
primaryLink: https://avd.aquasec.com/nvd/cve-2023-44487
# ConfigAuditReport — IaC/misconfiguration výsledky
apiVersion: aquasecurity.github.io/v1alpha1
kind: ConfigAuditReport
metadata:
name: replicaset-nginx-6d8d4f5b8b
namespace: production
spec:
scanner:
name: Trivy
version: "0.49.0"
summary:
criticalCount: 1
highCount: 2
mediumCount: 5
lowCount: 8
checks:
- checkID: KSV001
title: Process can elevate its own privileges
description: "A program inside the container can elevate its own privileges and run as root"
severity: MEDIUM
success: false
# ClusterComplianceReport — CIS Benchmark výsledky
apiVersion: aquasecurity.github.io/v1alpha1
kind: ClusterComplianceReport
metadata:
name: cis-k8s
spec:
compliance:
id: k8s-cis-1.27
title: CIS Kubernetes Benchmarks v1.23
description: CIS Kubernetes Benchmarks
version: "1.23"
cron: "0 */6 * * *"
Querying Operator výsledkov
# Zoznam všetkých vulnerability reportov
kubectl get vulnerabilityreports -A --sort-by='.report.summary.criticalCount'
# Detail pre konkrétny pod
kubectl get vulnerabilityreport -n production replicaset-nginx-6d8d4f5b8b-nginx -o yaml
# Nájdi všetky reporty s CRITICAL zraniteľnosťami
kubectl get vulnerabilityreports -A -o json \
| jq '.items[] | select(.report.summary.criticalCount > 0) | .metadata.name'
# CIS Benchmark report
kubectl get clustercompliancereport cis-k8s -o yaml
# ConfigAudit reporty pre namespace
kubectl get configauditreports -n production
# ExposedSecret reporty
kubectl get exposedsecretreports -A
Správa vulnerability databáz
Trivy databáza
# Manuálna aktualizácia
trivy image --download-db-only
# Zobraz info o aktuálnej DB
trivy image --show-version
# Vypni auto-update (pre air-gapped alebo rýchlejší CI)
trivy image --skip-db-update nginx:latest
# Custom DB location
trivy image --cache-dir /custom/cache nginx:latest
Air-gapped scenáre — Trivy
Pre prostredia bez prístupu na internet Trivy podporuje stiahnutie DB OCI artifact-u a jeho distribúciu cez privátny registry:
# 1. Na machine s internet prístupom — stiahni DB ako OCI artifact
trivy image --download-db-only
# DB je na ~/.cache/trivy/db/
# Alternatíva: stiahni oci-artifact
oras pull ghcr.io/aquasecurity/trivy-db:2 --output /tmp/trivy-db/
# 2. Pushni do privátneho registra
oras push myregistry.internal/trivy-db:2 \
--config /dev/null:application/vnd.aquasec.trivy.config.v1+json \
/tmp/trivy-db/db.tar.gz:application/vnd.aquasec.trivy.db.layer.v1.tar+gzip
# 3. V air-gapped prostredí použi privátny DB
trivy image \
--db-repository myregistry.internal/trivy-db \
--skip-check-update \
nginx:latest
Grype databáza
# Aktualizuj databázu
grype db update
# Zobraz info o DB
grype db status
# Importuj DB offline (vopred stiahnutá)
grype db import /path/to/grype-db.tar.gz
# Custom DB location
GRYPE_DB_CACHE_DIR=/custom/path grype nginx:latest
Porovnávanie SBOMs a attestations
Verifikácia Cosign attestation
# Verifikuj, že image má platný SBOM attestation
cosign verify-attestation \
--type cyclonedx \
--certificate-identity-regexp "https://github.com/myorg/myrepo/.*" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
ghcr.io/myorg/myapp:v1.2.3
# Extrahuj SBOM z attestation a ulož
cosign download attestation ghcr.io/myorg/myapp:v1.2.3 \
| jq -r 'select(.payload != null) | .payload | @base64d | fromjson | .predicate' \
> extracted-sbom.cdx.json
# Skontroluj SBOM cez Grype
grype sbom:extracted-sbom.cdx.json
SBOM diff — sledovanie zmien medzi verziami
# Porovnaj SBOM medzi verziami (pomocou syft a jq)
syft myapp:v1.2.2 -o json > sbom-v1.2.2.json
syft myapp:v1.2.3 -o json > sbom-v1.2.3.json
# Jednoduchý diff balíčkov
diff \
<(jq -r '.artifacts[] | "\(.name) \(.version)"' sbom-v1.2.2.json | sort) \
<(jq -r '.artifacts[] | "\(.name) \(.version)"' sbom-v1.2.3.json | sort)
# Nástroj sbom-utility pre pokročilý diff
sbom-utility diff --input-file sbom-v1.2.2.json --input-file2 sbom-v1.2.3.json
SLSA a in-toto provenance
Kompletný supply chain security stack kombinuje:
Syft/Trivy → SBOM (čo je v image)
Cosign → podpis SBOM a image
in-toto → attestation framework (predicate types)
SLSA → build provenance (kde a ako bol image zostavený)
Rekor → transparency log pre všetky attestations
Fulcio → CA pre krátkodobé certifikáty
Výsledok: plná auditovateľná cesta od source code po produkciu
Binary Authorization (Google Cloud) a Admission controllers môžu vynútiť, že iba images s platným SLSA L2+ provenance a SBOM attestation smú bežať v produkcii.
Performance charakteristiky
Merania sú orientačné — závisia od veľkosti image, počtu balíčkov a sieťového prístupu na DB update.
Scan time (nginx:latest, ~180 MB)
| Nástroj | Prvý scan (DB download) | Opakovaný scan | SBOM generovanie |
|---|---|---|---|
| Trivy | ~45 s | ~8 s | ~12 s |
| Grype | ~30 s | ~5 s | N/A |
| Syft | N/A | N/A | ~3 s |
| Syft → Grype | N/A | ~5 s | ~3 s + ~4 s |
DB veľkosť a pamäť
| Nástroj | DB na disku | RAM počas scanu |
|---|---|---|
| Trivy | ~250 MB | ~300 MB |
| Grype | ~150 MB | ~200 MB |
| Syft | N/A | ~150 MB |
Záver: Grype je rýchlejší a menej náročný na zdroje ako Trivy pre čistý vulnerability scan. Trivy trvá dlhšie, ale robí viac práce naraz. Syft je najrýchlejší pre generovanie SBOM.
Decision tree — kedy použiť čo
Potrebuješ SBOM generovanie?
├── Áno → Syft (najbohatší výstup, všetky formáty)
│ alebo Trivy (ak chceš jeden nástroj)
└── Nie → pokračuj
Máš existujúci SBOM a chceš ho scannovať?
├── Áno → Grype (SBOM-first, rýchly)
│ alebo Trivy (ak používaš Trivy všade)
└── Nie → pokračuj
Potrebuješ IaC misconfiguration scanning?
├── Áno → Trivy config (dobrý coverage)
│ alebo Checkov (ak potrebuješ custom Python rules)
└── Nie → pokračuj
Potrebuješ secrets detection?
├── Áno → Trivy (vstavaný)
│ alebo Gitleaks (špecializovaný, odporúčaný pre git history)
└── Nie → pokračuj
Potrebuješ K8s continuous scanning?
├── Áno → trivy-operator (CRD-based, GitOps-friendly)
└── Nie → pokračuj
Chceš jeden nástroj pre všetko v CI?
├── Áno → Trivy (najširší feature set)
└── Nie → Syft + Grype (lepšia separácia zodpovedností, ľahšie udržiavateľné)
Odporúčaná kombinácia pre produkciu
Pre väčšinu tímov odporúčame:
- Syft pre generovanie SBOM (SBOM ako artifact CI pipeline)
- Cosign pre podpísanie SBOM (keyless, Sigstore)
- Grype pre vulnerability scan SBOM (rýchly, CI gate)
- Trivy pre IaC + secrets scan (Trivy config v PR gate)
- trivy-operator pre continuous K8s scanning v produkcii
Táto kombinácia dáva najlepšiu separáciu zodpovedností, auditovateľnosť a výkon. Ak chceš minimalizovať počet nástrojov, Trivy alone pokryje 80% use-casov.
Integrácia s Dependency-Track
Dependency-Track (OWASP) je platforma pre kontinuálne sledovanie komponentov a zraniteľností na úrovni organizácie. Konzumuje SBOM a poskytuje dashboardy, metriky a alerting.
# Upload SBOM do Dependency-Track cez API
DTRACK_URL="https://dtrack.company.internal"
DTRACK_API_KEY="your-api-key"
PROJECT_UUID="your-project-uuid"
# Enkóduj SBOM do base64
ENCODED_SBOM=$(base64 -w 0 sbom.cdx.json)
# Upload
curl -X PUT "${DTRACK_URL}/api/v1/bom" \
-H "X-Api-Key: ${DTRACK_API_KEY}" \
-H "Content-Type: application/json" \
-d "{
\"project\": \"${PROJECT_UUID}\",
\"bom\": \"${ENCODED_SBOM}\"
}"
Dependency-Track potom automaticky porovnáva SBOM s NVD, GHSA a OSV a odosiela alerting pri nových CVE pre tvoje komponenty.
False positive management — praktické rady
False positives sú chronickým problémom vo vulnerability scanningu. Tím, ktorý nedokáže zvládnuť false positives, má dve možnosti: buď ignoruje všetky výsledky, alebo strávi dni triádzou. Oboje je katastrofické.
Prečo vznikajú false positives
- Transitive dependencies — balíček A závisí na balíčku B (vulnerable), ale A nikdy nevolá vulnerable kód B
- OS package vs vendored copy — scanner vidí napr.
libsslako OS balíček, ale aplikácia používa svoju vlastnú staticky linkovanú verziu - Version pinning bez semver — niektoré distribúcie backportujú bezpečnostné opravy bez zmeny verzie čísla (Debian, RHEL)
- Go/Rust static binaries — scanner musí rozpoznať zabudovanú verziu, čo nie vždy funguje spoľahlivo
Trivy false positive workflow
# 1. Skontroluj, či je CVE skutočne relevantná
trivy image --severity CRITICAL --format json nginx:latest \
| jq '.Results[].Vulnerabilities[] | {id: .VulnerabilityID, pkg: .PkgName, fixed: .FixedVersion, status: .Status}'
# 2. Ak je Status == "will_not_fix" alebo "end_of_life" → zvyčajne ignoruj
# 3. Pridaj do .trivyignore s expiry a dôvodom
# 4. Pre Debian/Ubuntu backport false positives
# Trivy pozná distribučné advisories — ak je Status == "fixed" v distro,
# ale verzia nevyzerá opravená, môže ísť o backport. Skontroluj:
trivy image --format json nginx:latest \
| jq '.Results[].Vulnerabilities[] | select(.VulnerabilityID == "CVE-XXXX-XXXX")'
# Hľadaj DataSource.ID — ak je to "debian" alebo "ubuntu" → dôveruj im
VEX — Vulnerability Exploitability eXchange
VEX je štandard (CycloneDX 1.4+, CSAF 2.0) pre dokumentovanie toho, prečo konkrétna CVE neovplyvňuje produkt. Je to formalizovaný false positive record, ktorý môžeš zdieľať so zákazníkmi a regulátormi.
// vex.cdx.json — VEX dokument
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"version": 1,
"vulnerabilities": [
{
"id": "CVE-2023-44487",
"analysis": {
"state": "not_affected",
"justification": "protected_by_mitigating_control",
"response": ["will_not_fix"],
"detail": "HTTP/2 is disabled in our nginx config. See nginx.conf line 12."
},
"affects": [
{
"ref": "pkg:deb/debian/nginx@1.25.3-1?distro=bookworm"
}
]
}
]
}
# Použitie VEX s Trivy
trivy image \
--vex vex.cdx.json \
nginx:latest
Footguns — bežné chyby
1. Stará databáza zraniteľností
Najčastejšia chyba: scan s DB starou viac ako 24 hodín. Nové CVE pribúdajú každý deň. Ak tvoj CI cachuje Trivy/Grype DB bez pravidelnej aktualizácie, skenujete slepí.
# WRONG — cache nikdy nevyprší
- name: Cache Trivy DB
uses: actions/cache@v4
with:
path: ~/.cache/trivy
key: trivy-db-${{ runner.os }}
# CORRECT — cache vyprší každých 24 hodín
- name: Cache Trivy DB
uses: actions/cache@v4
with:
path: ~/.cache/trivy
key: trivy-db-${{ runner.os }}-${{ steps.date.outputs.date }}
restore-keys: trivy-db-${{ runner.os }}-
2. Go a Rust statické binárky
Go a Rust kompilujú závislosti staticky do jedného binárneho súboru. Trivy a Grype vedia toto detekovať (čítajú Go build info z ELF sekcie go.buildinfo), ale iba ak:
- Binary je nekomprimovaný (UPX compressed binárky sú slepou škvrnou)
- Scanner má prístup k binárnemu súboru, nie iba k package manageru
# Overovacie — skontroluj, či Trivy vidí Go deps v image
trivy image --format json myapp:latest \
| jq '.Results[] | select(.Type == "gobinary") | .Vulnerabilities | length'
# Ak je výsledok 0 a image obsahuje Go binárky, niečo je zlé
3. "Clean" scan = bezpečný image (NIL)
Zero vulnerabilities neznamená bezpečný image. Znamená to: žiadne známe zraniteľnosti v databázach, ktoré scanner pozná. Zero-day zraniteľnosti, malware vložený do supply chain, backdoory — toto vulnerability scanner nezachytí. Runtime security (Falco, Tetragon) adresuje práve tú medzeru.
4. Ignorovanie transitive dependencies
Niektoré tímy skenujú iba priame závislosti (napr. iba requirements.txt top-level). Väčšina zraniteľností sa skrýva v transitive dependencies — závislostiach ich závislostí.
Syft a Trivy skenujú všetky vrstvy vrátane transitive. Nikdy nepoužívaj --skip-dirs na node_modules, vendor/, alebo podobné adresáre — práve tam sú transitive deps.
5. Severity threshold bez kontextu
# BAD — failne CI na akúkoľvek HIGH, vrátane will_not_fix
trivy image --exit-code 1 --severity HIGH myapp:latest
# BETTER — failni iba na fixable HIGH/CRITICAL
trivy image \
--exit-code 1 \
--severity HIGH,CRITICAL \
--ignore-unfixed \
myapp:latest
Bez --ignore-unfixed budeš blokovať deploy na CVE, pre ktoré neexistuje oprava — čo je antiproduktívne a vedie k ignorovaniu alertov.
6. Rozdielne výsledky medzi nástrojmi
Trivy a Grype môžu vracať rôzne výsledky pre rovnaký image. Dôvody:
- Rôzne databázy (Trivy má vlastnú trivy-db — open-source, agreguje NVD/GHSA/Red Hat/distro advisories; Grype používa Anchore's vuln-db z rovnakých zdrojov)
- Rôzna detekcia balíčkov (napr. Grype môže nájsť package, ktorý Trivy preskočí)
- Rôzna severita (CVSS skóre sa líši medzi NVD a distribúciami)
Riešenie: použi oba v kritických pipeline a deduplikuj výsledky. Ak jedno hlási CRITICAL a druhé nie, investiguj manuálne.
Pre-commit integrácia
# .pre-commit-config.yaml
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.92.0
hooks:
- id: terraform_validate
# Trivy pre secret scanning v kóde
- repo: https://github.com/aquasecurity/trivy
rev: v0.49.0
hooks:
- id: trivy-docker-image-scan
args: ['--scanners', 'secret', '--exit-code', '1']
Pre Dockerfile scanning v pre-commit:
# Wrapper script pre pre-commit hook
#!/bin/bash
trivy config \
--severity HIGH,CRITICAL \
--exit-code 1 \
--quiet \
"$@"
Sumár a odporúčania
Nástroj Rola Kedy použiť
─────────────────────────────────────────────────────────────────
Syft SBOM generátor Vždy — generuj SBOM ako CI artifact
Grype Vulnerability scan Keď chceš rýchly SBOM-first scan
Trivy All-in-one Keď chceš jeden nástroj; K8s scanning
trivy-op K8s continuous scan Produkcia — live vulnerability posture
Cosign SBOM attestation Supply chain — podpisuj každý release
Odporúčaný stack pre nový projekt v 2026:
- Trivy v CI PR gate:
trivy image --exit-code 1 --severity CRITICAL --ignore-unfixed - Syft pri každom release tagu → SBOM artifact
- Cosign attest SBOM → uložený v OCI registry
- Grype scan SBOM → výsledky do GitHub Security (SARIF)
- trivy-operator v K8s → VulnerabilityReport CRDs, alerting cez Prometheus/AlertManager
- Dependency-Track → organizačný dashboard a long-term tracking
Investícia do tohto stacku je jednorázová (3-5 dní nastavenia), ale výnos je kontinuálny: viditeľnosť do supply chain, compliance s reguláciami a schopnosť reagovať na nové CVE v hodinách, nie týždňoch.