Trivy Container-Sicherheitsscan hat sich zum De-facto-Standard für die Erkennung von Schwachstellen in Docker-Images entwickelt, bevor sie die Produktion erreichen. Wenn du dich jemals gefragt hast, wie Angreifer bekannte CVEs in Basis-Images wie ubuntu:20.04 oder node:18 ausnutzen, oder ob dein Dockerfile Secrets preisgibt, liefert Trivy die Antwort in Sekunden. Diese Anleitung behandelt Installation, Scan-Strategien, CI/CD-Integration und wie du Trivy-Befunde interpretierst und darauf reagierst — ohne in falschen Positiven zu ertrinken.

Voraussetzungen

  • Docker installiert und laufend (Docker 20.10+)
  • Linux-, macOS- oder Windows-Arbeitsstation (WSL2)
  • Grundlegende Vertrautheit mit Docker-Images und Dockerfiles
  • Eine CI/CD-Plattform (GitHub Actions, GitLab CI oder Jenkins) für Pipeline-Integration
  • Root- oder sudo-Zugriff für systemweite Trivy-Installation (oder Binär-Installation verwenden)

Trivy installieren

Trivy wird als einzelnes statisches Binär ohne externe Abhängigkeiten ausgeliefert. Der schnellste Weg unter Linux:

curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
trivy --version

Unter Ubuntu/Debian kannst du das Aqua Security apt-Repository für verwaltete Updates hinzufügen:

sudo apt-get install wget apt-transport-https gnupg lsb-release -y
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] 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 -y

Unter macOS mit Homebrew: brew install trivy

Trivy lädt seine Schwachstellendatenbank beim ersten Aufruf herunter. Erzwinge ein Datenbankupdate jederzeit mit trivy image --download-db-only.

Docker-Images auf Schwachstellen scannen

Der Kernbefehl ist unkompliziert:

trivy image nginx:latest

Trivy lädt das Image herunter, falls es nicht lokal gecacht ist, entpackt die Schichten und prüft jedes installierte OS-Paket und jede Sprachabhängigkeit gegen seine Schwachstellendatenbank (NVD, GitHub Advisory, Alpine secdb und andere). Die Ausgabe zeigt CVE-IDs, Schweregrad, installierte Version und die korrigierte Version, wenn verfügbar.

Nach Schweregrad filtern

Standardmäßig zeigt Trivy alle Schweregrade von UNKNOWN bis CRITICAL. In der Praxis solltest du dich auf umsetzbare Befunde konzentrieren:

trivy image --severity HIGH,CRITICAL nginx:latest

Nicht behobene Schwachstellen ignorieren

Viele CVEs haben noch keine verfügbare Korrektur. Nutze --ignore-unfixed, um sie zu überspringen und dich auf das zu konzentrieren, was du tatsächlich beheben kannst:

trivy image --severity HIGH,CRITICAL --ignore-unfixed nginx:latest

Ausgabeformate

Trivy unterstützt mehrere Ausgabeformate für verschiedene Anwendungsfälle:

# Menschenlesbare Tabelle (Standard)
trivy image nginx:latest

# JSON für programmatische Verarbeitung
trivy image --format json --output results.json nginx:latest

# SARIF für GitHub Security Tab Integration
trivy image --format sarif --output results.sarif nginx:latest

# CycloneDX SBOM
trivy image --format cyclonedx --output sbom.json nginx:latest

Das SARIF-Format integriert sich direkt mit dem GitHub Security Tab und zeigt Schwachstellen-Annotationen inline in Pull Requests an.

Dockerfiles und IaC-Fehlkonfigurationen scannen

Trivys config-Scanner prüft Dockerfiles, Kubernetes-Manifeste, Terraform und Helm-Charts auf Sicherheitsfehlkonfigurationen, bevor sie deployed werden:

# Dockerfile scannen
trivy config ./Dockerfile

# Ganzes Verzeichnis scannen (Kubernetes-Manifeste, Terraform)
trivy config ./k8s/

# Helm-Charts scannen
trivy config --helm-values values.yaml ./charts/myapp

Häufige Dockerfile-Befunde umfassen: Ausführung als Root, ADD statt COPY, fehlendes HEALTHCHECK, Exposition sensibler Ports und fehlende Pinning von Basis-Image-Digests.

Secrets und sensible Daten erkennen

Trivy kann Image-Schichten und Dateisysteme auf versehentlich eingebaute Secrets scannen:

# Secret-Scan für ein Image aktivieren
trivy image --scanners secret nginx:latest

# Lokales Verzeichnis auf Secrets scannen
trivy fs --scanners secret ./src/

Trivy erkennt AWS-Schlüssel, GitHub-Tokens, private SSH-Schlüssel, Datenbankverbindungsstrings und Hunderte andere Secret-Muster. Das ist besonders wertvoll, um Secrets abzufangen, die im Quellcode committed wurden und in einer Docker-Schicht gelandet sind.

Vergleich mit Alternativen

FunktionTrivyGrypeSnykClair
OS-Paket-CVEsJaJaJaJa
SprachabhängigkeitenJaJaJaNein
IaC-FehlkonfigurationenJaNeinJaNein
Secret-ScanningJaNeinJaNein
SBOM-GenerierungJaJaJaNein
LizenzApache 2.0Apache 2.0ProprietärApache 2.0
CI/CD-IntegrationNativNativNativBegrenzt
Offline-ModusJaJaNeinTeilweise

Trivys Vorteil ist die Breite — es kombiniert Schwachstellen-Scanning, Fehlkonfigurationserkennung, Secret-Scanning und SBOM-Generierung in einem einzigen Binär ohne laufenden Server oder Datenbank.

Trivy in CI/CD-Pipelines integrieren

GitHub Actions

name: Container-Sicherheitsscan

on:
  push:
    branches: [main]
  pull_request:

jobs:
  trivy-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Docker-Image bauen
        run: docker build -t myapp:${{ github.sha }} .

      - name: Trivy Schwachstellen-Scanner ausführen
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:${{ github.sha }}
          format: sarif
          output: trivy-results.sarif
          severity: HIGH,CRITICAL
          exit-code: 1
          ignore-unfixed: true

      - name: Trivy-Scan-Ergebnisse zum GitHub Security Tab hochladen
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: trivy-results.sarif

Die Einstellung exit-code: 1 lässt die Pipeline fehlschlagen, wenn kritische oder hohe CVEs gefunden werden. if: always() beim SARIF-Upload stellt sicher, dass Ergebnisse sichtbar sind, auch wenn der Scan-Schritt fehlschlägt.

GitLab CI

trivy-scan:
  image: aquasec/trivy:latest
  stage: test
  script:
    - trivy image --exit-code 1 --severity CRITICAL --ignore-unfixed $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  allow_failure: false

Praxisbeispiel

Du hast eine Produktionsanwendung, die node:16 als Basis-Image verwendet. Dein Sicherheitsteam stellt fest, dass die CI/CD-Pipeline Container-Images vor dem Deployment nie validiert. Du hast 48 Stunden, um ein Scan-Gate zu implementieren.

Schritt 1 — Aktuelles Image prüfen:

trivy image node:16 --severity HIGH,CRITICAL --ignore-unfixed

Das zeigt 47 HIGH- und 12 CRITICAL-CVEs im Basis-Image — die meisten durch Upgrade auf node:18-alpine behoben.

Schritt 2 — Dockerfile aktualisieren:

# Vorher
FROM node:16

# Nachher
FROM node:18-alpine

Schritt 3 — Erneut scannen zur Bestätigung:

trivy image node:18-alpine --severity HIGH,CRITICAL --ignore-unfixed

Die Alpine-Variante reduziert die CVE-Anzahl von 59 auf 3 (alle ohne Korrektur).

Schritt 4 — CI-Gate hinzufügen:

Füge den GitHub Actions Workflow oben hinzu. Alle zukünftigen PRs werden blockiert, wenn CRITICAL-CVEs eingeführt werden.

Schritt 5 — Auch IaC scannen:

trivy config ./k8s/ --severity HIGH,CRITICAL

Das zeigt zwei Probleme: Ein Deployment läuft als Root und eine readOnlyRootFilesystem Security-Context-Einstellung fehlt.

Stolperfallen und Sonderfälle

Veraltete Schwachstellendatenbank: Trivy cached seine Datenbank lokal. In CI-Umgebungen führe trivy image --download-db-only als separaten Cache-Schritt aus, um redundante Downloads zu vermeiden.

Authentifizierung bei privaten Registries: Exportiere Credentials als Umgebungsvariablen vor dem Scan:

export TRIVY_USERNAME=meinbenutzer
export TRIVY_PASSWORD=meinpasswort
trivy image meine-registry.beispiel.com/meine-app:latest

Falsch-Positive: Einige CVEs werden in Bibliotheken gemeldet, die deine Anwendung nie aufruft. Nutze .trivyignore, um bekannte Falsch-Positive zu unterdrücken:

# .trivyignore
CVE-2022-12345  # Nicht ausnutzbar — Bibliothek wird zur Laufzeit nicht aufgerufen

Alpine musl vs glibc: Alpine-basierte Images melden weniger CVEs, weil Alpine musl libc verwendet und das Alpine-Sicherheitsteam aggressiv patcht. Das ist keine “fehlende” Abdeckung — es spiegelt echte Unterschiede im Bibliotheks-Ökosystem wider.

Multi-Arch-Images: Gib beim Scannen von Multi-Arch-Images immer die Plattform an: trivy image --platform linux/amd64 myapp:latest.

Trivy vs. Laufzeit-Sicherheit: Trivy findet Schwachstellen zur Build-Zeit. Es ersetzt keine Laufzeit-Sicherheitstools wie Falco, die unerwartetes Verhalten in laufenden Containern erkennen.

Fehlerbehebung

Fehler “No such image”: Trivy kann das Image weder lokal finden noch herunterladen. Überprüfe Image-Name, Tag und Registry-Credentials.

Datenbankdownload-Fehler in air-gapped Umgebungen: Lade das Datenbankpaket auf einer internetfähigen Maschine herunter mit trivy image --download-db-only, dann übertrage das Verzeichnis ~/.cache/trivy/ auf den isolierten Host.

Hoher Speicherverbrauch bei großen Images: Nutze --parallel 1, um die gleichzeitige Schichtverarbeitung zu reduzieren: trivy image --parallel 1 myapp:latest.

Exit-Code 1, aber keine kritischen CVEs angezeigt: Prüfe, ob --ignore-unfixed fehlt — nicht behobene kritische CVEs können den Exit-Code auslösen, auch wenn du nur behebbare Probleme erwartet hast.

Scan-Timeout in CI: Setze TRIVY_TIMEOUT=10m, um den Standard-Timeout von 5 Minuten für große Images zu verlängern.

Zusammenfassung

  • Trivy ist ein Ein-Binär-Scanner für CVEs, Fehlkonfigurationen, Secrets und SBOM-Generierung
  • Führe trivy image --severity HIGH,CRITICAL --ignore-unfixed myapp:latest als Basisscan aus
  • Nutze --exit-code 1 in CI/CD, um Deployments mit kritischen Schwachstellen zu blockieren
  • Kombiniere trivy image (Laufzeit) mit trivy config (Dockerfile/IaC) für vollständige Abdeckung
  • Alpine-basierte Images reduzieren die CVE-Angriffsfläche drastisch
  • Nutze .trivyignore, um bestätigte Falsch-Positive zu unterdrücken und Alert-Fatigue zu reduzieren
  • Lade SARIF-Ergebnisse zum GitHub Security Tab hoch für Inline-Annotationen in PRs
  • Trivy ersetzt keine Laufzeit-Sicherheit — kombiniere es mit Falco für Defense-in-Depth

Verwandte Artikel