ГлавнаяБлогTrivy vs Grype: Container Image Tarayıcılarını 60 Gün Production'da Karşılaştırdım
Security & Compliance

Trivy vs Grype: Container Image Tarayıcılarını 60 Gün Production'da Karşılaştırdım

Emre Ferit Aslantaş17 июня 2026 г.12 dkСтатья
trivy grype container-security cve devsecops image-scanning ci-cd
Sponsored

Mart ayında Zenth prod imajının base layer'ında bir glibc CVE'si gözden kaçtı ve bunu Hetzner'ın abuse departmanından gelen bir mail ile öğrendim. O hafta GitHub Actions pipeline'ıma "her build sonrası container scan" adımını ekledim — ama hangi aracı kullanacağıma karar verirken iki gün kaybettim. Sonunda iki tanesini birden çalıştırmaya başladım: Aqua Trivy ve Anchore Grype. 60 gün sonra hâlâ iki tarayıcıyı birden çalıştırıyorum; sebepleri aşağıda. Bu yazı bir "hangisi daha iyi" tartışması değil — ikisini de aynı imajlarda gerçekten kullanan birinin notları.

Test Yatağı: Ne Taradım?

Karşılaştırmayı net tutmak için sabit bir imaj seti seçtim:

| İmaj | Base | Yaklaşık Boyut | Layer Sayısı | |---|---|---|---| | efa-agent:prod | python:3.12-slim | ~480 MB | 14 | | zenth-api:prod | node:22-alpine | ~210 MB | 9 | | zenth-web:prod | nginx:1.27-alpine | ~85 MB | 6 | | mlx-bridge:prod | python:3.12-bullseye | ~1.1 GB | 18 |

Hepsi haftada en az iki kere yeniden build oluyor (efa-agent günde 1-2 kere). Tarama sonuçlarını PostgreSQL'de küçük bir tabloda biriktirdim (scan_id, tool, image, critical, high, duration_ms, scanned_at) — 60 gün sonra ~840 satır birikti. Sayıların büyük kısmı bu tablodan, gerisi tek tek not aldıklarımdan geliyor.

Versiyonlar ve Kurulum

  • Trivy 0.58.x (Aqua) — tek statik binary, Homebrew + GitHub Actions resmi action var.
  • Grype 0.85.x (Anchore) — yine statik binary, kendi DB'si var (grype db update).

İkisini de Mac Mini M4 üzerinde lokal denedim, sonra Zenth VPS'inde CI runner üzerinde production'a aldım. Kurulum iki tarafta da 5 dakika sürmedi:

# Trivy
brew install trivy
trivy image --severity HIGH,CRITICAL zenth-api:prod

# Grype
brew install grype
grype zenth-api:prod --fail-on high

CLI ergonomisi açısından ikisi de iyi, ama Grype --fail-on flag'i daha doğrudan; Trivy'de CI hatası için --exit-code 1 --severity HIGH,CRITICAL yazmak gerekiyor. Küçük bir detay ama 5 farklı pipeline'da copy-paste yapıyorsanız fark ediyor.

Round 1: Scan Süresi

İlk benchmark scan hızıydı. CI runner üzerinde aynı imajı sırayla 10 kere tarayıp medyan değerleri aldım. DB cache'li (yani ilk çalışmadan sonra) ölçüm:

| İmaj | Trivy (medyan) | Grype (medyan) | |---|---|---| | efa-agent:prod | 4.2 sn | 6.8 sn | | zenth-api:prod | 2.1 sn | 3.4 sn | | zenth-web:prod | 1.6 sn | 2.5 sn | | mlx-bridge:prod | 9.5 sn | 14.1 sn |

Trivy her imajda ~35-40% daha hızlıydı. Beklediğim bir sonuç değildi — ikisi de Go ile yazılmış, ikisi de OS package manager metadata'sını parse ediyor. Sebep büyük olasılıkla Grype'ın Syft'i SBOM üretimi için ön plana koyması: her tarama önce tam bir SBOM çıkarıp sonra CVE eşleştirmesi yapıyor. Trivy ise tek geçişte hem paket listesini hem eşleştirmeyi yapıyor.

İlk vector DB indirme süresi de fark ediyor — Trivy ilk açılışta ~38 MB cache çekiyor, Grype ~120 MB. Self-hosted runner'da bunu CI cache'e koymazsanız her cold start'ta 8-12 saniye kaybediyorsunuz.

Round 2: CVE Doğruluğu (False Positive / Negative)

Burası işin sıkıcı kısmı. 60 günde topladığım toplam HIGH/CRITICAL bulgularını şöyle dağıttım:

  • İkisi de buldu: 142 CVE — bunlar muhtemelen "gerçek" sinyal.
  • Sadece Trivy buldu: 23 CVE
  • Sadece Grype buldu: 31 CVE

Beni şaşırtan, sadece-Grype-buldu setiydi. Manuel olarak NVD üzerinden 31'inin ~20'sini doğruladım (Python pip paketlerindeki bazı transitive bağımlılıklar). Trivy'nin Python package indexing'i daha kısıtlı — özellikle --scanners vuln,secret,config flag'ini açmasanız bile, Grype'ın pip dependency tree'sini daha derin gezdiğini gördüm.

Trivy'nin avantajı ise OS paket katmanında. Debian/Alpine seviyesindeki "yeni yayınlanmış" CVE'leri Grype'tan birkaç gün önce yakalıyor (Aqua'nın DB güncelleme cycle'ı daha sık). Mart sonunda çıkan bir libxml2 CVE'sini Trivy aynı gün, Grype 3 gün sonra gösterdi.

False positive oranı kontrolü için elimde net bir yöntem yoktu — her bulguyu manuel doğrulamak realist değil. Spot-check yaptığım 25 bulgudan:

  • Trivy: 25/25 doğrulanabildi (yani sıfır false positive görmedim spot check'te)
  • Grype: 22/25 gerçek, 3'ü ya "fixed in latest patch but distro hasn't rebuilt" durumu ya da yanlış versiyon eşleşmesiydi.

Yani Grype daha geniş ağ atıyor, daha fazla yakalıyor, ama biraz daha gürültülü. Trivy daha temiz, ama dependency tree'de bazı şeyleri ıskalıyor.

Round 3: SBOM Üretimi

İmajların SBOM'unu üretmek istediğimde Grype'ın yan ürünü Syft devreye giriyor. Trivy de SBOM üretiyor ama Syft daha olgun:

# Syft (Grype'ın eklentisi)
syft zenth-api:prod -o cyclonedx-json > sbom.json

# Trivy
trivy image --format cyclonedx zenth-api:prod > sbom-trivy.json

İki SBOM'u diff'leyince Syft çıktısı ~15-20% daha fazla paket listeliyordu — özellikle dotfiles, vendored libraries ve embedded binary'leri yakalıyor. Compliance audit için bu fark önemli. Zenth için müşteri compliance taleplerine cevap verirken Syft çıktısını kullanıyorum.

Round 4: CI/CD Entegrasyonu (GitHub Actions)

Pipeline tarafında ikisinin de resmi action'ı var:

# .github/workflows/scan.yml — Trivy adımı
- name: Trivy scan
  uses: aquasecurity/trivy-action@0.28.0
  with:
    image-ref: ghcr.io/efa/zenth-api:${{ github.sha }}
    format: sarif
    output: trivy.sarif
    severity: HIGH,CRITICAL
    exit-code: '1'

# Grype adımı
- name: Grype scan
  uses: anchore/scan-action@v4
  with:
    image: ghcr.io/efa/zenth-api:${{ github.sha }}
    fail-build: true
    severity-cutoff: high
    output-format: sarif
    output-file: grype.sarif

Her iki SARIF çıktısını da GitHub Code Scanning'e yüklüyorum. Burada çakışma oldu: Aynı CVE iki kez raporlanınca Security tab'inde duplikasyon görünüyor. Çözüm olarak Trivy'yi "blocker" (build'i durduran), Grype'ı sadece "informational" (rapor üreten ama build'i kırmayan) modda tutuyorum:

- name: Grype scan (informational)
  uses: anchore/scan-action@v4
  with:
    image: ghcr.io/efa/zenth-api:${{ github.sha }}
    fail-build: false
    severity-cutoff: high
    output-format: sarif
    output-file: grype.sarif
  continue-on-error: true

Bu kurulum sayesinde Trivy bana "production'a çıkmamalı" sinyalini, Grype ise "bunlara da bakmalısın" listesini veriyor. İkisini ayırınca pipeline gürültüsü dramatik olarak azaldı.

Vazgeçtiğim Şeyler

Üç deneme yapıp pes ettiğim şeyleri saklamak istiyorum, çünkü genelde "fail" hikayeleri rehberlerde geçmiyor:

  1. Trivy --scanners license modunu devreye almayı denedim. Niyet: GPL bulaşması yok mu kontrol etmek. Çıktı, sadece base layer için 400+ satır lisans dosyası — gerçek bir false positive denizi. İki gün filtre yazdıktan sonra Syft + manuel review'a geçtim.
  2. Grype DB'sini self-hosted offline mode'da çalıştırmayı denedim (air-gapped runner senaryosu için). DB indirme ve cache invalidation süreci CI cache ile uyumsuz çalıştı; build her seferinde 90+ MB indirdi. Tekrar online mode'a döndüm.
  3. Trivy operator'ı K8s cluster'ıma kurmayı denedim. Çalıştı, ama Docker Desktop K8s üzerinde admission webhook'lar M4 RAM'imi 24 GB üzerinden ekstra ~600 MB ısırdı. Tek node lab cluster için aşırı. Production K8s'iniz varsa makul.

Karar Matrisi (Benim İçin)

Şu an iki tarayıcıyı şu rollerle tutuyorum:

  • Trivy = "blocker" pre-merge gate. Hızlı, az gürültü, OS layer için keskin.
  • Grype + Syft = "deeper inspection" — haftalık rapor, compliance SBOM'u, language-specific dependency taraması.
  • Hiçbiri runtime security yerini tutmuyor; o iş için Falco düşünüyorum (henüz lab'da).

Notlar (60 günden sonra)

  • Hız önemliyse → Trivy. Pre-merge gate için ideal.
  • Daha derin language-level CVE taraması istiyorsan → Grype.
  • SBOM compliance çıktısı gerekiyorsa → Syft (Grype'la beraber gelen).
  • DB güncelliği için Trivy biraz daha çevik; ama bu fark bazen sadece 2-3 gün.
  • Sıfır false positive yok; her iki çıktıyı da kör imzalamayın. 60 günde gördüğüm: Grype'ın ekstra bulgularının ~30%'u "fix yok" veya "exploitable değil" sınıfında.

İki aracı birden çalıştırmanın CI maliyeti? Aylık self-hosted runner üzerinde ~3-4 dakika ek CI süresi ve negligible diskboyutu. Bu fiyata ikisini de tutmamak için iyi bir sebep göremiyorum.

Sponsored

Еженедельная рассылка DevOps

Новые обзоры инструментов, сравнения и тренды DevOps — еженедельно на вашу почту.