Trivy ile Container Görüntü Güvenlik Taraması: Kurulum, CI/CD Entegrasyonu ve SBOM Rehberi 2026

Trivy 0.57 ile container imajlarını, Terraform/Kubernetes manifest'lerini ve Git depolarını nasıl tarayacağınızı, CycloneDX SBOM üretimini, secret yakalamayı ve CI/CD'ye kırılan build'lerle entegrasyonu saldırgan gözlü anlatıyorum.

Güncelleme: 18 Ağustos 2026

Trivy, Aqua Security tarafından geliştirilen açık kaynaklı bir güvenlik tarayıcısıdır ve container imajlarındaki CVE'leri, Infrastructure-as-Code (IaC) yanlış yapılandırmalarını, sızdırılmış secret'ları ve yazılım tedarik zinciri risklerini tek bir komutla ortaya çıkarır. Açıkçası, son iki yılda gördüğüm hemen her CI/CD boru hattında bir yerlerde çalışıyor; sebebi de basit: tek binary, düşük sürtünme, geniş kapsam. Bu rehberde 2026 sürümü olan Trivy 0.57'yi Linux üzerinde kuracağım, bir container imajını saldırgan gözüyle söküp her bulguya somut bir sertleştirme kontrolü eşleyeceğim. Sonda GitHub Actions ile CI/CD entegrasyonu ve Trivy Operator'la Kubernetes kümesi taraması da var. Hadi başlayalım.

  • Trivy 0.57, tek binary olarak dağıtılır; OS paketleri, dil bağımlılıkları, IaC dosyaları, secret'lar ve lisanslar için bütünleşik bir tarayıcı sunar.
  • trivy image komutu bir imajı yerelde çekmeden registry üzerinde tarayabilir; --severity HIGH,CRITICAL --exit-code 1 bayrağı CI pipeline'ını doğru şekilde kırar.
  • Trivy, CycloneDX 1.5 ve SPDX 2.3 formatında SBOM üretir; bunu Sigstore cosign ile imzalayarak SLSA seviye 3'e ulaşabilirsiniz.
  • trivy config Kubernetes YAML, Terraform, Dockerfile ve Helm chart'lar için 500'ü aşkın yerleşik politika ile misconfig tarar.
  • Trivy Operator, kümedeki her Pod için otomatik VulnerabilityReport CRD'si üretir; ClusterComplianceReport ile NSA/CIS uyum durumunu izler.
  • Yanlış yapılandırılan .trivyignore ve --ignore-unfixed kullanımı en sık atlanan CVE'leri saldırganların istismarına açar; sonda bu tuzakları tek tek gösteriyorum.

Trivy nedir ve ne için kullanılır?

Trivy, tek bir statik Go binary'si olarak dağıtılan bir "all-in-one" güvenlik tarayıcısıdır. Amacı, DevSecOps pipeline'ında güvenliği "shift-left" etmek. Yani bir imaj production'a çıkmadan çok önce, geliştiricinin laptop'unda veya CI'da bilinen zafiyetleri, yanlış yapılandırmaları ve gizli anahtarları yakalamak. Bir pentester olarak testlerimde en sık şu senaryoyla karşılaşıyorum: geliştirici node:18 imajını kullanmış, altta libc6'da 22 CRITICAL CVE var, kimsenin haberi yok (bu tam olarak geçen ay bir müşteride yakaladığım bir senaryoydu). Trivy bu boşluğu 3 saniyede kapatır.

2026 itibarıyla Trivy'nin desteklediği tarama hedefleri şunlardır: OCI/Docker container imajları, yerel dosya sistemi ve Git depoları, Kubernetes kümeleri, VM disk imajları (VMDK, QCOW2), Cloud tarayıcı (AWS hesabı taraması), IaC dosyaları (Terraform, CloudFormation, Kubernetes, Helm, Dockerfile), SBOM dosyaları (CycloneDX, SPDX) ve Java jar/war arşivleri. Zafiyet veri tabanı aquasecurity/trivy-db deposundan çekilir ve NVD, Red Hat OVAL, Debian Security Tracker, GitHub Security Advisories dahil 20'yi aşkın kaynağı birleştirir. Bu, tek bir apt-get changelog yorumundan gelen ipuçlarına bel bağlamak zorunda kalmamanız demek.

Aynı ekosistemdeki başka araçlarla nasıl kesiştiğine gelince: runtime tarafta anomali yakalamak için Falco ile Kubernetes runtime güvenliği tarafına geçmeniz gerekir; Trivy imajın içine bakar, Falco imajın kernelde ne yaptığına bakar. Host sıkılaştırma denetimi için Lynis ile Linux güvenlik denetimi tamamlayıcıdır. Katmanları birbirine karıştırmayın; Trivy yamanın olup olmadığını söyler, çalıştığında ne yaptığını değil.

Trivy kurulumu ve veri tabanı başlatma

Trivy'nin en temiz kurulumu resmi apt/yum deposundan gelir; böylece trivy self-update beklemeden dağıtımın paket yöneticisiyle güncel kalır. Debian/Ubuntu için (2026 itibarıyla Ubuntu 24.04 ve Debian 13 desteklidir):

# Aqua Security deposunun imza anahtarını ekle
sudo apt-get install -y wget gnupg
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key \
  | sudo gpg --dearmor -o /usr/share/keyrings/trivy.gpg

echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] \
  https://aquasecurity.github.io/trivy-repo/deb generic main" \
  | sudo tee /etc/apt/sources.list.d/trivy.list

sudo apt-get update
sudo apt-get install -y trivy

# Sürümü doğrula
trivy --version
# Version: 0.57.1
# Vulnerability DB: 2026-08-17 00:00:00 +0000 UTC

RHEL/Rocky/Alma tarafında (dnf 5 ile):

sudo tee /etc/yum.repos.d/trivy.repo <<'EOF'
[trivy]
name=Trivy repository
baseurl=https://aquasecurity.github.io/trivy-repo/rpm/releases/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://aquasecurity.github.io/trivy-repo/rpm/public.key
EOF
sudo dnf install -y trivy

İlk çalıştırmada Trivy, ~/.cache/trivy/db altına yaklaşık 55 MB'lık zafiyet veri tabanını indirir. Air-gapped ortamda çalışıyorsanız veri tabanını önceden trivy image --download-db-only ile indirip --cache-dir üzerinden monte edebilir, hatta veri tabanını OCI artifact olarak kendi registry'nize aynalayabilirsiniz. CI'da her koşuda 55 MB indirmemek için --db-repository bayrağıyla ghcr.io mirror'ınıza yönlendirin.

Container imajlarını nasıl tararsınız?

En temel kullanım tek satırdır: trivy image nginx:1.27. Ancak varsayılan çıktı geliştiriciyi CVE denizinde boğar (ilk denemede 400+ satır görebilirsiniz). Bir saldırgan olarak ben yalnızca "işletilebilir" olanlarla ilgilenirim: fix'i olan, HIGH veya CRITICAL, script-friendly formatta. İşte gerçek pipeline'larda kullandığım komut:

trivy image \
  --severity HIGH,CRITICAL \
  --ignore-unfixed \
  --scanners vuln,secret \
  --format json \
  --output nginx-report.json \
  --exit-code 1 \
  nginx:1.27

Bayrakları parçalayalım. --severity HIGH,CRITICAL gürültüyü keser; NEGLIGIBLE ve LOW için ekip zamanı harcamaz. --ignore-unfixed yamanın henüz çıkmadığı CVE'leri atlar — bu tartışmalı bir bayraktır; ben genelde build-fail aşamasında kullanır, ayrı bir reporting koşusunda kapatırım. --exit-code 1 herhangi bir bulguda çıkış kodunu 1 yapar; CI bunu görür ve build'i kırar. --format json çıktıyı jq ile parse etmenizi ya da DefectDojo gibi bir bulgu havuzuna aktarmanızı sağlar.

Bir imajın katmanları arasında hangi paketin hangi katmanda geldiğini görmek istiyorsanız trivy image --show-suppressed --scanners vuln --format table --layer-info nginx:1.27 kullanın. Bu, "CVE'yi hangi FROM satırından miras aldım?" sorusuna cevap verir. Saldırganın taktiği tersinedir: en dipteki base imajın kırılganlığını arar, çünkü onu değiştirmek en pahalıdır ve genelde ertelenir. Bunu bilerek base imajlarınızı Distroless veya Chainguard Wolfi gibi minimum yüzey alanına sahip imajlara taşımak Trivy raporunuzu tek gecede yarıya indirebilir.

Registry üzerinde uzaktan tarama

Trivy imajı yerel Docker daemon'ına docker pull etmek zorunda değildir; registry'ye doğrudan bağlanır. Bu, CI runner'ında Docker daemon yoksa ya da 2 GB'lık imajı indirmek istemediğinizde kritiktir:

TRIVY_USERNAME=ci-bot TRIVY_PASSWORD="$REG_TOKEN" \
  trivy image \
    --image-src remote \
    ghcr.io/mycorp/api:sha-$GITHUB_SHA

IaC ve yanlış yapılandırma taraması

Trivy 2022'de Chainguard'ın tfsec ve cfsec araçlarını devraldı; bugün trivy config alt komutu Terraform, CloudFormation, Kubernetes, Helm ve Dockerfile için 500'ün üzerinde yerleşik politikayı çalıştırır. Politikalar Rego (Open Policy Agent) diliyle yazılmıştır ve aquasecurity/trivy-checks deposundan güncellenir.

# Terraform kodunu tara
trivy config --severity HIGH,CRITICAL ./infrastructure/

# Kubernetes manifest'lerini tara
trivy config --skip-dirs vendor --misconfig-scanners kubernetes ./k8s/

# Dockerfile'ı tara
trivy config ./Dockerfile

Çıktıda tipik olarak "AVD-KSV-0014: securityContext.readOnlyRootFilesystem: false" gibi bir bulgu görürsünüz. Saldırganın gözünde bu, bir RCE elde ettiği anda /tmp/x'e bir binary yazıp kalıcılık kurabileceği bir Pod demektir. Küçük bir ayar, koca bir zincir. Karşı kontrolü Rego kuralına eşleyip securityContext.readOnlyRootFilesystem: true ve emptyDir ile yazılabilir bir /tmp mount ederek koyarsanız aynı istismar zinciri kırılır. Sadelik burada güvenlik.

Kendi kurumsal politikanızı yazmak için --policy ./custom-checks/ --namespaces user bayrağıyla Rego dosyalarınızı yükleyebilirsiniz. Bu, "yalnızca onaylı base imajlarımızdan gelen Pod'lara izin ver" gibi kurumsal kuralları CI'a taşımanın en temiz yoludur.

SBOM üretimi ve tedarik zinciri güvenliği

SBOM (Software Bill of Materials), bir yazılımdaki tüm bileşenlerin listesidir. ABD Executive Order 14028'den sonra federal tedarikçiler için zorunlu hale geldi; 2026 itibarıyla AB'nin Cyber Resilience Act'i de benzer bir yükümlülük getiriyor. Trivy iki standart formatta SBOM üretir:

# CycloneDX 1.5 formatında SBOM
trivy image --format cyclonedx \
  --output api-sbom.cdx.json \
  ghcr.io/mycorp/api:v1.4.0

# SPDX 2.3 formatında (Linux Foundation standardı)
trivy image --format spdx-json \
  --output api-sbom.spdx.json \
  ghcr.io/mycorp/api:v1.4.0

Bir SBOM'u ürettikten sonra onu sonradan zafiyet tarayabilirsiniz — bu, imajı elden çıkardıktan aylar sonra bile "bu sürümde artık kaç CVE var?" sorusunu cevaplamanızı sağlar:

trivy sbom --severity HIGH,CRITICAL api-sbom.cdx.json

Tam bir supply-chain hijyeni için SBOM'u Sigstore cosign ile imzalayın ve OCI artifact olarak registry'ye yükleyin:

cosign attest --predicate api-sbom.cdx.json \
  --type cyclonedx \
  ghcr.io/mycorp/api:v1.4.0

Böylece deploy anında Kyverno veya OPA Gatekeeper, imajın imzalı ve doğrulanmış SBOM'u olmadıkça çalışmasına izin vermeyebilir. CycloneDX resmi spesifikasyonu alan tanımlarını ve VEX (Vulnerability Exploitability eXchange) uzantısını detaylıca açıklar.

Secret ve gömülü anahtar taraması

Bir pentester olarak "erişim" için tek ihtiyacım genelde bir dosyada unutulmuş bir AWS access key'dir. Yıllar içinde .env.bak, eski Slack export'ları, tek satırlık test script'leri, imaj katmanlarında kalmış ~/.aws/credentials... hep aynı hikaye. Trivy secret tarayıcısı yerleşik 40+ pattern ile Docker imajlarında, Git tarihçesinde ve dosya sisteminde bu tür girdileri yakalar. Etkinleştirmek için --scanners secret yeter:

trivy fs --scanners secret --severity HIGH,CRITICAL ./

Örnek çıktı:

tests/fixtures/aws.env (secrets)
================================
Total: 1 (HIGH: 1, CRITICAL: 0)

HIGH: aws-access-key-id (aws-access-key-id)
════════════════════════════════════════
AWS Access Key ID
──────────────────────────────
 tests/fixtures/aws.env:3
────────────
   1   # test creds - DO NOT COMMIT
   2
   3 [ AKIAIOSFODNN7EXAMPLE ]
   4

Bunu Git pre-commit hook'una bağlayarak (ya da trivy repo ile bir Git URL'sini doğrudan tarayarak) sırların depoya girmesini önleyebilirsiniz. Yakalanmış ama artık geçersiz secret'lar için .trivyignore.yaml ile bulguyu susturabilir, ama not düşerek: bir secret git tarihçesine bir kez girerse döndürmediğiniz sürece "silmek" bir güvenlik önlemi değildir.

GitHub Actions ile CI/CD entegrasyonu

2026'da Trivy'yi GitHub Actions'a bağlamak için Aqua'nın resmi aquasecurity/[email protected] action'ı en pratik yoldur. Aşağıdaki workflow, PR açıldığında imajı build eder, Trivy ile tarar, sonuçları GitHub Advanced Security'nin Code Scanning sekmesine SARIF olarak yükler ve CRITICAL bulguda build'i kırar:

name: container-security
on:
  pull_request:
    branches: [main]

jobs:
  scan:
    runs-on: ubuntu-24.04
    permissions:
      contents: read
      security-events: write
    steps:
      - uses: actions/checkout@v4

      - name: Build image
        run: docker build -t local/api:${{ github.sha }} .

      - name: Run Trivy vulnerability scan
        uses: aquasecurity/[email protected]
        with:
          image-ref: local/api:${{ github.sha }}
          format: sarif
          output: trivy-results.sarif
          severity: HIGH,CRITICAL
          ignore-unfixed: true
          exit-code: '1'

      - name: Upload SARIF to GitHub Security
        if: always()
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: trivy-results.sarif

      - name: Generate and upload SBOM
        uses: aquasecurity/[email protected]
        with:
          image-ref: local/api:${{ github.sha }}
          format: cyclonedx
          output: sbom.cdx.json
      - uses: actions/upload-artifact@v4
        with:
          name: sbom
          path: sbom.cdx.json

if: always() notu önemli: build önceki adımda kırılsa bile bulguları Security sekmesine yüklemek ekibin diff'i görmesini sağlar. GitLab CI'da paralel yaklaşım, resmi registry.gitlab.com/security-products/trivy imajını job içinde kullanmaktır; Jenkins'te trivy image --format template --template "@contrib/junit.tpl" ile JUnit raporu üretip publishJUnit ile göstermek en temiz akıştır.

Kubernetes kümesi taraması ve Trivy Operator

CI'da build sırasında imaj taramak yeterli değildir; runtime'da hangi imajın kümede döndüğü zamanla değişir. Trivy Operator, Helm chart olarak kurulduğunda kümedeki her Pod, Deployment, DaemonSet için otomatik olarak VulnerabilityReport, ConfigAuditReport ve ExposedSecretReport CRD'leri üretir.

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.metricsFindingsEnabled=true \
  --version 0.24.0

kubectl get vulnerabilityreports -A
kubectl get clustercompliancereports

ClusterComplianceReport özellikle güçlüdür: NSA/CISA Kubernetes Hardening Guide, CIS Kubernetes Benchmark v1.9 ve PCI-DSS v4 için hazır uyum raporları üretir. Bir denetim öncesi bu raporu Prometheus'a çekip Grafana'da uyum yüzdesini takip edebilirsiniz. Ayrıca operator.metricsFindingsEnabled=true ile trivy_vulnerability_id metriği açılır ve Alertmanager'a "yeni CRITICAL bulundu" alarmı bağlayabilirsiniz.

Trivy vs Grype vs Clair karşılaştırması

2026'da açık kaynak container tarayıcıları alanında üç ciddi seçenek var: Aqua Trivy, Anchore Grype ve Red Hat/Quay tarafından geliştirilen Clair. İşte doğrudan karşılaştırma:

ÖzellikTrivy 0.57Grype 0.82Clair 4.7
Dağıtım biçimiTek binary + OperatorTek binarySunucu (Postgres gerekli)
KapsamVuln, IaC, secret, SBOM, K8s, cloudYalnızca vuln + SBOMYalnızca vuln (registry entegre)
SBOM üretimiCycloneDX + SPDX yerleşikSyft'e delegeYok (yalnızca tüketir)
IaC / misconfig500+ Rego politikasıYokYok
Veri tabanı boyutu~55 MB (OCI mirror)~180 MB SQLitePostgres, GB seviyesinde
Kurulum karmaşıklığıDüşükDüşükYüksek (uzun süredir Quay bağımlı)
CI için idealEvetEvetHayır (server modelinde)
Runtime K8sTrivy Operator ileYokYok

Kısa cevap: eğer bir CI/CD pipeline'ında tek bir araca ihtiyacınız varsa Trivy tartışmasız birinci seçimdir; kapsamı en geniş, sürtünmesi en düşüktür. Grype daha yalın ve daha hızlıdır, yalnızca vuln taraması istediğiniz durumlarda değerlidir. Clair'i sıfırdan kurmayı 2026'da önermiyorum; kendisi hâlâ iyi bir araç ama operasyonel yükü Trivy Operator'la karşılaştırıldığında haklı çıkmıyor. (Bu benim gözlemim; ekibiniz Quay üzerinde konumlanmışsa hikaye biraz farklı olabilir.)

Politika, ignore dosyaları ve sık yapılan hatalar

Trivy'yi başarısızlığa uğratmanın en kolay yolu, "gürültüyü azaltmak" bahanesiyle yanlış bulguları susturmaktır. Ekiplerde en sık gördüğüm üç anti-pattern:

  1. Kör .trivyignore: Bir CVE'yi ID'siyle susturmak, o CVE'nin başka bir bağımlılıkta yeniden ortaya çıktığında bulgunun kaçmasına neden olur. Bunun yerine .trivyignore.yaml'ın yapılandırılmış hâlini kullanın ve expired_at alanı zorunlu tutun. Örnek:
vulnerabilities:
  - id: CVE-2024-45491
    paths:
      - usr/lib/x86_64-linux-gnu/libxml2.so.2
    statement: "Yalnızca CLI'de kullanılıyor, ağa açık değil"
    expired_at: 2026-11-30
  1. Sürekli --ignore-unfixed: Yaması olmayan CVE'leri saklamak "temiz build" hissi verir ama saldırganın gözünde bunlar altın madenidir çünkü kimsenin izlemediği kalıcı zayıflıklardır. En az haftada bir unfixed dahil tarayıp bulguları güvenlik ekibine kuyruklayın.
  2. Yalnızca CRITICAL'a bakmak: Bir HIGH SSRF ile bir CRITICAL DoS arasındaki gerçek işletilebilirlik farkı, ekseriya HIGH lehinedir. CVSS'ye değil, kendi hedef mimarinizde neyin gerçekten istismar edilebilir olduğuna bakın; VEX belgesiyle bu kararı SBOM'a iliştirin.

Bir başka pratik ipucu: Trivy'nin sonuçlarını CI'da karşılaştırmalı göstermek isterseniz trivy image --format json | jq ile önceki tarama JSON'u ile diff alın ve yalnızca yeni bulgularda build'i kırın. Eski borcu yeniden düşürüp geliştiriciyi hayal kırıklığına uğratmaktansa, "regression zero-tolerance, mevcut borç haftalık plan" akışı daha sürdürülebilirdir.

Sık sorulan sorular

Trivy ne için kullanılır?

Trivy; container imajları, IaC dosyaları, Git depoları ve Kubernetes kümelerindeki bilinen CVE'leri, yanlış yapılandırmaları ve sızdırılmış secret'ları taramak için kullanılır. DevSecOps pipeline'ında "shift-left" güvenlik kontrolünün en yaygın açık kaynak seçimidir.

Trivy imajı Docker daemon olmadan tarayabilir mi?

Evet. --image-src remote bayrağıyla Trivy, container imajını yerel Docker daemon'a çekmeden doğrudan registry'den okur. Bu, sidecar Docker-in-Docker'a ihtiyaç duymayan hafif CI runner'larda idealdir.

Trivy hangi SBOM formatlarını üretir?

Trivy 0.57, CycloneDX 1.5 ve SPDX 2.3 formatlarında SBOM üretir. Ürettiği SBOM'u daha sonra trivy sbom komutuyla yeniden tarayarak zaman içinde eklenen CVE'leri bulabilirsiniz.

Trivy ile Grype arasındaki fark nedir?

Trivy vuln taramasının yanında IaC misconfig, secret taraması, SBOM üretimi ve Kubernetes runtime taraması yapar; Grype yalnızca CVE odaklıdır ve SBOM için Syft'e delege eder. CI'da tek araca ihtiyacınız varsa Trivy daha kapsamlıdır.

Trivy Operator prod kümesinde performans sorunu yaratır mı?

Varsayılan ayarlarla 100+ node'lu kümelerde tarama Job'ları CPU spike'larına yol açabilir. operator.scanJobsConcurrentLimit değerini 10 civarında tutmak ve trivy.resources.requests ile Job kaynaklarını sınırlamak sorunu ortadan kaldırır.

Trivy air-gapped ortamda çalışır mı?

Evet. trivy image --download-db-only ile veri tabanını internetli bir hostta indirip ~/.cache/trivy/db dizinini offline hosta kopyalayabilir ya da --db-repository bayrağıyla kendi OCI registry mirror'ınızı gösterebilirsiniz.

Felix Lindqvist
Yazar Hakkında Felix Lindqvist

Penetration tester and OSCP holder. Reverse engineers misconfigured servers for a living and writes about what he finds.