ProgrammierungTechnologie

Container-Image-Scan mit Trivy gegen bekannte Schwachstellen für viele Projekte

netcomputing.de Redaktion26. August 202610 Min. Lesezeit

Zusammenfassung

Wer viele Docker-Images baut, trägt oft unbemerkt bekannte Schwachstellen aus dem Basisimage ins fertige Image, weil weder Secret-Scanner noch Renovate das gebaute Image prüfen. Trivy (Version 0.74.0) scannt das Image gegen die Datenbank trivy-db und stoppt in GitHub Actions den Build nur bei CRITICAL- und HIGH-Funden. Eine .trivyignore-Datei akzeptiert eine geprüfte CVE ohne Fix einzeln, und ein veraltetes Basisimage bleibt die häufigste Ursache für zu viele Funde auf einmal.

Ein Docker-Image trägt neben dem eigenen Anwendungscode ein komplettes Basisimage mit eigenen Betriebssystempaketen, und jedes dieser Pakete kann eine bereits veröffentlichte, bekannte Schwachstelle enthalten: eine CVE, kurz für Common Vulnerabilities and Exposures, die öffentlich vergebene Kennung für eine dokumentierte Sicherheitslücke. Ein Secret-Scan wie Gitleaks findet fest codierte Zugangsdaten im eigenen Quellcode. Ein Dependency-Bot wie Renovate meldet veraltete Einträge in der eigenen package.json oder im requirements.txt. Beide Werkzeuge lesen aber nur, was im Repository liegt. Was am Ende tatsächlich im gebauten Image steckt, ein Alpine- oder Debian-Basisimage mit eigenen, vom Anwendungscode unabhängig versionierten Paketen, sehen sie nie. Genau diese Lücke schließt ein Image-Scanner, indem er das fertige Image nach dem Build gegen eine laufend aktualisierte Schwachstellendatenbank prüft.

Trivy ist ein quelloffenes Sicherheitswerkzeug von Aqua Security, aktuell in Version 0.74.0 vom 14. August 2026. Es deckt laut eigener Dokumentation mehrere Scan-Ziele ab: Container-Images, Dateisysteme, Git-Repositories, virtuelle Maschinenabbilder, Kubernetes-Cluster, SBOM-Dateien (Software Bill of Materials, ein maschinenlesbares Verzeichnis aller Komponenten eines Artefakts) sowie Infrastructure-as-Code-Dateien wie Terraform- oder Kubernetes-Manifeste. Für eine Organisation, die viele eigenständige Images baut und ausliefert, zählt vor allem der Image-Scan: Ein einziger Befehl vergleicht jedes installierte Betriebssystempaket und jede erkannte Sprachbibliothek gegen trivy-db, die eigene Datenbank des Projekts, die Aqua Security aus mehr als einem Dutzend externer Quellen zusammenführt und laut eigenem Repository alle sechs Stunden neu baut.

Systemvoraussetzungen

Ein Trivy-Aufbau für viele Projekte braucht wenige, aber genau aufeinander abgestimmte Bausteine. Die folgende Tabelle nennt den Stand vom 26. August 2026.

KomponenteVersion oder AnforderungZweck
Trivy (CLI)v0.74.0, veröffentlicht am 14. August 2026Scan-Engine für Container-Images, Dateisysteme, Git-Repositories, Kubernetes-Cluster und IaC-Dateien
trivy-db (Schwachstellendatenbank)wird automatisch aus ghcr.io/aquasecurity/trivy-db geladen, laut eigenem Repository alle 6 Stunden neu gebautBündelt Advisories aus der NVD, der GitHub Advisory Database und den Sicherheitsdatenbanken der Linux-Distributionen
Docker oder eine kompatible Container-Laufzeitzum Bauen des zu scannenden Images nötigErzeugt das Image, das trivy image anschließend prüft
aquasecurity/trivy-actionv0.36.0, veröffentlicht am 22. April 2026Offizielle GitHub Action, bindet Trivy in einen Workflow ein und cacht die Datenbank standardmäßig
.trivyignore oder .trivyignore.yamlTextdatei im Wurzelverzeichnis des RepositoriesUnterdrückt einzelne, geprüfte CVE-IDs, ohne den Scan insgesamt abzuschalten
GitHub-Actions-Runnerz. B. ubuntu-latest, mit Netzwerkzugriff auf ghcr.ioFührt Image-Build und Scan in der Pipeline aus

Systemarchitektur

Ein Image-Scan hat zwei Kontrollpunkte, die sich ergänzen: den lokalen Lauf während der Entwicklung und den Pflichtlauf in der Pipeline, kurz bevor ein Image in die Registry gelangt. Trivy führt in beiden Fällen denselben Abgleich aus. Es liest die installierten Paketversionen aus jeder Schicht des Images, lädt oder aktualisiert dabei trivy-db und meldet jeden Treffer mit Schweregrad, betroffener Paketversion und, sofern vorhanden, der Version, die das Problem behebt.

flowchart TD
    A[Team baut ein neues Docker-Image] --> B[trivy image scannt das gebaute Image]
    B --> C[trivy-db wird aus der Registry geladen und zwischengespeichert]
    C --> D[Installierte Pakete werden gegen bekannte CVEs abgeglichen]
    D --> E[Trivy meldet jeden Fund mit Schweregrad und Fixed Version]
    E -->|CRITICAL oder HIGH gefunden| F[Pipeline-Job schlaegt fehl]
    E -->|nur MEDIUM LOW oder UNKNOWN| G[Job besteht, Funde bleiben im Log sichtbar]
    F --> H[Team prueft die Fixed-Version-Spalte im Bericht]
    H -->|Fix verfuegbar| I[Basisimage oder Paket aktualisieren und neu bauen]
    H -->|Kein Fix verfuegbar, Risiko geprueft| J[CVE-ID einzeln in .trivyignore eintragen]
    J --> K[Naechster Lauf ignoriert genau diese ID]
    I --> B
    G --> L[Image wird in die Registry gepusht]

Über viele Projekte hinweg trägt dieser Ablauf zwei Entscheidungen, die sich nicht in jedem Repository neu stellen sollten: welcher Schweregrad einen Build stoppt, und wie ein Team mit einer Schwachstelle umgeht, für die es noch keinen Fix gibt. Beide Entscheidungen lassen sich zentral als Regel festlegen und danach in jedem Repository gleich anwenden, ähnlich wie eine geteilte Konfiguration bei einem Dependency-Bot. Ohne diese Festlegung im Voraus landet jedes Team beim ersten CRITICAL-Fund vor derselben Frage: sofort stoppen, oder erst einmal weiterbauen.

Schritt-für-Schritt-Umsetzung

Container-Image lokal mit Trivy scannen

Der lokale Scan läuft gegen ein bereits gebautes Image, nicht gegen den Quellcode. Trivy braucht dafür nur den Image-Namen und lädt trivy-db beim ersten Aufruf automatisch.

  1. Image bauen. docker build -t registry.example.com/team/checkout-service:2026.08.1 . erzeugt das zu prüfende Image.
  2. Scan starten. trivy image registry.example.com/team/checkout-service:2026.08.1 prüft alle Betriebssystempakete und erkannten Sprachbibliotheken.
  3. Nach Schweregrad filtern. Der Parameter --severity grenzt die Ausgabe ein, etwa auf die beiden höchsten Stufen.
  4. Exit-Code für die Pipeline setzen. Ohne --exit-code beendet sich Trivy laut eigener Dokumentation immer mit 0, auch bei einem CRITICAL-Fund.
trivy image --severity HIGH,CRITICAL --exit-code 1 registry.example.com/team/checkout-service:2026.08.1

Trivy kennt fünf Schweregrade: UNKNOWN, LOW, MEDIUM, HIGH und CRITICAL. Der Bericht listet zu jedem Fund die installierte Paketversion und, sofern verfügbar, eine Fixed-Version-Spalte. Steht dort ein Wert, behebt genau diese Paketversion die Schwachstelle. Bleibt die Spalte leer, existiert nach aktuellem Stand der Datenbank kein Fix, und ein Update allein löst das Problem nicht.

GitHub-Actions-Workflow mit Schweregrad-Gate einrichten

In der Pipeline übernimmt die offizielle Action aquasecurity/trivy-action denselben Scan, eingebettet in einen Workflow, der zuerst das Image baut und danach zweimal scannt: einmal, um jeden Fund unabhängig vom Schweregrad im Log sichtbar zu machen, und ein zweites Mal, um den Job ausschließlich bei CRITICAL- oder HIGH-Funden zu stoppen.

name: image-scan
on:
  push:
    branches: [main]
  pull_request:

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

      - name: Image bauen
        run: docker build -t registry.example.com/team/checkout-service:${{ github.sha }} .

      - name: Alle Funde protokollieren
        uses: aquasecurity/trivy-action@v0.36.0
        with:
          image-ref: 'registry.example.com/team/checkout-service:${{ github.sha }}'
          format: 'table'
          severity: 'UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL'
          exit-code: '0'

      - name: Build bei CRITICAL oder HIGH stoppen
        uses: aquasecurity/trivy-action@v0.36.0
        with:
          image-ref: 'registry.example.com/team/checkout-service:${{ github.sha }}'
          format: 'table'
          severity: 'CRITICAL,HIGH'
          exit-code: '1'

Der erste Scan-Schritt setzt exit-code: '0' und zeigt deshalb jeden Fund, ohne den Job jemals zu stoppen. Der zweite Schritt engt die Prüfung über severity auf die beiden höchsten Stufen ein und setzt exit-code: '1', sodass ausschließlich ein CRITICAL- oder HIGH-Fund den Job scheitern lässt. MEDIUM-, LOW- und UNKNOWN-Funde bleiben dadurch sichtbar im Protokoll, ohne einen Merge zu blockieren. Für den Versions-Verweis @v0.36.0 gilt dieselbe Vorsicht wie bei jeder GitHub Action: Ein Tag lässt sich per Force-Push auf einen anderen Commit verschieben, ein vollständiger Commit-SHA nicht. Genau das nutzten Angreifer im März 2026 aus, als sie nach Angaben von Aqua Security binnen rund zwölf Stunden fast alle bestehenden Versions-Tags von trivy-action auf kompromittierte Commits umschrieben.

Eine geprüfte Schwachstelle ohne verfügbaren Fix akzeptieren

Fehlt zu einer gemeldeten CVE eine Fixed Version, bleiben zwei Wege: warten, bis ein Fix erscheint, oder das Risiko nach Prüfung bewusst akzeptieren. Für den zweiten Fall liest Trivy eine Datei namens .trivyignore im Wurzelverzeichnis des Repositories und blendet jede darin gelistete CVE-ID aus dem Bericht aus, ohne den restlichen Scan zu beeinflussen.

# Kein Patch verfuegbar, vom Security-Team am 20.08.2026 geprueft
CVE-2018-14618

# Risiko akzeptiert bis zum naechsten Wechsel des Basisimages
CVE-2019-14697 exp:2027-01-01

Der optionale Zusatz exp:JJJJ-MM-TT hinter einer CVE-ID setzt ein Ablaufdatum. Nach diesem Datum taucht der Fund wieder im Bericht auf, statt dauerhaft unsichtbar zu bleiben. Für feinere Regeln, etwa eine Ausnahme nur für einen bestimmten Dateipfad oder ein einzelnes Paket, bietet Trivy zusätzlich das YAML-Format .trivyignore.yaml mit den Feldern id, paths, statement und expired_at, aufgerufen über das Flag --ignorefile.

Häufige Fehlerquellen

  • Ein beweglicher Tag statt eines Commit-SHA bei der GitHub Action. Im März 2026 schrieben Angreifer nach Angaben von Aqua Security binnen rund zwölf Stunden nahezu alle bestehenden Versions-Tags von aquasecurity/trivy-action auf kompromittierte Commits um, sodass ein Workflow mit einem beweglichen Tag unbemerkt einen Credential-Stealer ausführen konnte. Aqua empfiehlt seither, die Action über den vollständigen Commit-SHA einzubinden statt über einen Tag, weil sich ein Tag per Force-Push verschieben lässt, ein Commit-SHA dagegen nicht.
  • Ein aufgeblähtes oder veraltetes Basisimage erzeugt hunderte Funde auf einmal. Ein volles Debian- oder Ubuntu-Basisimage mit Compiler, Paketverwaltung und Shell-Werkzeugen bringt Pakete mit, die die eigene Anwendung zur Laufzeit nie braucht, aber jedes davon zählt für den Scan. Ein Wechsel auf ein aktuell gepflegtes, schlankes Basisimage senkt die Paketzahl und damit die Fundliste unmittelbar. Das Distroless-Projekt von Google Container Tools nennt in der eigenen Dokumentation ein verbessertes Signal-Rausch-Verhältnis von CVE-Scannern als einen der Hauptgründe für ein schlankes Basisimage.
  • Der Scan läuft ohne --exit-code. Trivy beendet sich laut eigener Dokumentation standardmäßig mit dem Exit-Code 0, selbst bei einem CRITICAL-Fund, solange das Flag nicht gesetzt ist. Ein Pipeline-Schritt ohne --exit-code zeigt zwar die Fundliste an, lässt den Job aber immer erfolgreich durchlaufen.
  • Eine zu breite Regel statt einer einzelnen CVE-ID in .trivyignore. Wird die Datei mit einem zu weiten Eintrag eingesetzt, statt einzelne CVE-IDs mit Begründung zu listen, verschwinden auch neue, noch nie geprüfte Funde aus dem Bericht. Jede Zeile gehört an eine konkrete, im Team dokumentierte CVE-ID, mit Begründung als Kommentar und nach Möglichkeit mit einem Ablaufdatum über exp:JJJJ-MM-TT.
  • Ein eigener Container-Aufruf verzichtet auf das eingebaute Caching der Action. Wer Trivy in der Pipeline direkt per Container statt über aquasecurity/trivy-action aufruft, verliert das Caching für trivy-db, das die offizielle Action laut eigener Dokumentation standardmäßig aktiviert und im Verzeichnis $GITHUB_WORKSPACE/.cache/trivy ablegt. Ohne dieses Caching zieht jeder einzelne Lauf die komplette Datenbank erneut aus der GitHub Container Registry.
  • Schwachstellen- und Fehlkonfigurationsfunde werden nicht getrennt behandelt. Trivy meldet CVEs und Fehlkonfigurationen, etwa in einem Dockerfile, im selben Bericht, wenn beide Scanner-Typen aktiv sind. Ein Team, das nur auf den Exit-Code reagiert, ohne den Scanner-Typ zu unterscheiden, kann einen Build wegen einer Dockerfile-Fehlkonfiguration stoppen, obwohl eigentlich nur bekannte CVEs gaten sollten.

Häufig gestellte Fragen

Scannt Trivy nur Container-Images, oder auch andere Ziele?

Trivy scannt deutlich mehr als nur Container-Images. Neben Docker- und OCI-Images deckt das Werkzeug laut eigener Dokumentation auch Dateisysteme, Git-Repositories, virtuelle Maschinenabbilder, Kubernetes-Cluster, SBOM-Dateien (Software Bill of Materials, ein maschinenlesbares Verzeichnis aller Komponenten eines Artefakts) und Infrastructure-as-Code-Dateien wie Terraform- oder Kubernetes-Manifeste ab. Für eine Organisation mit vielen eigenständigen Docker-Images bleibt der Image-Scan der praktisch wichtigste dieser Fälle, weil dort die Betriebssystempakete des Basisimages liegen, die kein anderes Werkzeug im üblichen Werkzeugkasten prüft.

Woher bezieht Trivy seine Daten zu bekannten Schwachstellen?

Trivy bezieht seine Schwachstellendaten aus der eigenen Datenbank trivy-db, die Aqua Security automatisiert aus mehr als einem Dutzend externer Quellen zusammenführt und laut eigenem Repository alle sechs Stunden neu baut. Dazu zählen die National Vulnerability Database der US-Regierung, die GitHub Advisory Database für Sprachpakete wie npm, PyPI oder RubyGems, sowie die Sicherheitsdatenbanken der jeweiligen Linux-Distribution, etwa das Alpine-Secdb oder der Debian Security Bug Tracker. Die fertige Datenbank liegt als Artefakt in der GitHub Container Registry unter ghcr.io/aquasecurity/trivy-db und wird bei jedem Trivy-Lauf automatisch geladen.

Was passiert mit einer gemeldeten Schwachstelle, für die es noch keinen Fix gibt?

Eine gemeldete Schwachstelle ohne verfügbaren Fix erscheint im Bericht mit einer leeren Fixed-Version-Spalte, während eine bereits behobene Schwachstelle dort die Paketversion nennt, die das Problem löst. Dieser Unterschied entscheidet über die Reaktion: Steht eine Fixed Version im Bericht, aktualisiert ein Update des Basisimages oder der betroffenen Bibliothek die Situation direkt. Fehlt sie, bleibt nur die geprüfte Risikoakzeptanz über eine .trivyignore-Datei, in der die einzelne CVE-ID mit Begründung und optional einem Ablaufdatum eingetragen wird, statt den ganzen Scan für das betroffene Image abzuschalten.

Ersetzt Trivy einen Secret-Scanner oder ein Dependency-Update-Tool wie Renovate?

Trivy ersetzt weder einen Secret-Scanner noch ein Dependency-Update-Tool wie Renovate, weil alle drei Werkzeuge unterschiedliche Risikoquellen prüfen. Ein Secret-Scanner wie Gitleaks findet fest codierte Zugangsdaten im eigenen Quellcode, und Renovate meldet veraltete Einträge in den eigenen Paket-Manifesten. Trivy prüft dagegen das fertig gebaute Container-Image selbst, einschließlich der Betriebssystempakete im Basisimage, die in keinem der beiden anderen Werkzeuge jemals auftauchen. Eine Organisation mit vielen Repositories und vielen Images braucht deshalb typischerweise alle drei Prüfungen nebeneinander, nicht eine anstelle der anderen.

Quellen

  1. Trivy GitHub-Releases (aktuelle Version v0.74.0), Aqua Security / Trivy-Projekt (GitHub), abgerufen am 2026-08-26
  2. Trivy-Dokumentation: Vulnerability Scanner und Datenquellen, Trivy-Projekt, abgerufen am 2026-08-26
  3. Trivy-Dokumentation: Filtering und .trivyignore, Trivy-Projekt, abgerufen am 2026-08-26
  4. Trivy-Dokumentation: Exit-Code- und Schweregrad-Konfiguration, Trivy-Projekt, abgerufen am 2026-08-26
  5. aquasecurity/trivy-action: Versionsstand und Workflow-Beispiele, Aqua Security (GitHub), abgerufen am 2026-08-26
  6. Trivy-Supply-Chain-Angriff im März 2026: Einordnung und Empfehlungen, Aqua Security, abgerufen am 2026-08-26
  7. trivy-db: Aktualisierungsrhythmus und Verteilung über GHCR, Aqua Security (GitHub), abgerufen am 2026-08-26
  8. Distroless-Projekt: Begründung für minimale Basisimages, Google Container Tools (GitHub), abgerufen am 2026-08-26

Der Content wurde mit Hilfe von KI erstellt, vor allem in der Recherche und Vorformulierung. Prüfung und Abnahme durch unsere Redaktion.