/툴 리뷰/Trivy vs Grype: A Practical Guide to Choosing a Container Vulnerability Scanner
Tool ReviewsTrivyGrype

Trivy vs Grype: A Practical Guide to Choosing a Container Vulnerability Scanner

If you're stuck choosing between Trivy and Grype, decide on three things: DB source, false-positive handling, and CI fail policy. This practical guide covers CI integration examples, SBOM workflows, and recommendations by situation.

Trivy vs Grype: A Practical Guide to Choosing a Container Vulnerability Scanner

Trivy vs Grype: A Practical Guide to Choosing a Container Vulnerability Scanner

Let's start with the conclusion. Choose Trivy if you want one tool that also covers IaC, secrets, and Kubernetes. Choose Grype if your pipeline is SBOM-centric, you already use syft, or you need fine-grained ignore rules. Both are free and open source with similar GitHub stars, which is why picking one feels so hard—but the real differentiators aren't stars. They're DB source, false-positive handling, and CI fail policy. Use this post to decide in five minutes and ship it the same day with copy-paste CI snippets.

Why you should put a vulnerability scanner in CI now

SBOM submission is becoming de facto mandatory under U.S. Executive Order 14028 and the EU Cyber Resilience Act (CRA). The core of DevSecOps is "shift-left"—moving security checks from runtime into the build. Blocking CRITICAL vulnerabilities before an image hits the registry and before a PR is merged is now the standard. Trivy and Grype are the two leading open-source scanners competing for that slot.

5-minute hands-on: install and first scan

Run both against the same image (python:3.12-slim) and you'll feel the differences immediately.

Bash
# Trivy (Aqua Security)
brew install trivy
trivy image python:3.12-slim

# Grype (Anchore)
brew install grype
# 또는: curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
grype python:3.12-slim

The first run takes tens of seconds for both because they download the vulnerability DB; after that, cache makes subsequent scans finish in a few seconds. The output columns are similar too.

  • Trivy: Library(package) / Vulnerability(CVE-ID) / Severity / Installed Version / Fixed Version / Title
  • Grype: NAME(package) / INSTALLED(installed version) / FIXED-IN(fixed version) / TYPE / VULNERABILITY(CVE-ID) / SEVERITY

The point is that both tell you which package, which version, which CVE, and which version to upgrade to. Getting different result counts on the same image is normal—that's because of the DB source differences in the table below.

Head-to-head comparison

ItemTrivyGrype
Vendor / orgAqua SecurityAnchore
Vulnerability DBTrivy DB (Aqua-curated, distributed as OCI artifacts on GitHub)grype-db (NVD, GitHub Security Advisory, and distro security feeds combined)
First-run speedSeconds after DB downloadSeconds after DB download (similar)
Speed after cacheFastFast (Grype is usually a bit faster)
Scan targetsImages, filesystems, Git repos, IaC (Terraform, etc.), secrets, k8sImages, filesystems, SBOM-centric
SBOM generationBuilt-in (--format cyclonedx/spdx)Via companion tool syft
Ignore false positives.trivyignoreignore: block in .grype.yaml
LicenseApache 2.0 / freeApache 2.0 / free

Why the result counts differ: Trivy uses Aqua's processed and aggregated DB; Grype uses Anchore's DB that merges NVD with each distro's security feeds. Even for the same CVE, package matching rules and severity classification can differ, so counts diverge. Neither is "wrong"—they just have different data-source policies.

Wiring it into CI: fail the build + ignore false positives

GitHub Actions (Trivy)

YAML
- name: Trivy scan
  uses: aquasecurity/trivy-action@master
  with:
    image-ref: 'myorg/myapp:${{ github.sha }}'
    severity: 'CRITICAL,HIGH'
    exit-code: '1'   # CRITICAL/HIGH 발견 시 1 → 잡 실패 → PR 머지 차단

GitLab CI (Trivy)

YAML
scan:
  script:
    - trivy image --exit-code 1 --severity CRITICAL,HIGH $IMAGE

Grype

Bash
grype myorg/myapp:latest --fail-on high
# high 이상(= high, critical) 발견 시 exit-code 1

exit-code 1 is the key. When the CI job fails, branch protection blocks the PR merge, so developers upgrade the vulnerable package before merge. That's shift-left in practice.

Conditional suppression of false positives

Instead of blanket suppression, conditional suppression plus an expiry date is the operational best practice. The most dangerous thing is turning something off and forgetting about it.

TEXT
# .trivyignore — CVE 한 줄씩, 만료일 지정 가능
CVE-2023-12345 exp:2026-12-31
YAML
# .grype.yaml — vulnerability/package/fix-state 조건으로 정밀 무시
ignore:
  - vulnerability: CVE-2023-12345
  - package:
      name: openssl
    fix-state: not-fixed   # 아직 패치 안 나온 건 한시적으로 무시

Practical tip: I exclude "not-fixed" CVEs (no patched version yet) from build-breaking and track them in a separate backlog. If you break the build on things the team can't fix, they'll just turn the scanner off. That's where Grype's fix-state condition shines.

SBOM workflow differences

Grype pairs naturally with syft, which is also from Anchore.

Bash
syft myorg/myapp:latest -o syft-json | grype
# 또는 미리 만들어둔 SBOM 재스캔
grype sbom:./sbom.json

Trivy can generate an SBOM on its own, without an extra tool, and rescan that SBOM.

Bash
trivy image --format cyclonedx -o sbom.json python:3.12-slim
trivy sbom sbom.json

Both cover SPDX and CycloneDX. The difference is whether you generate the SBOM with one tool (Trivy) or pipe a syft-generated SBOM straight through (Grype + syft). If you already have a syft pipeline, Grype feels natural. If you don't want another SBOM tool, Trivy alone is enough.

Choose by situation

Your situationRecommendation
All-in-one for images plus IaC, secrets, and k8s manifestsTrivy
Minimize learning curve, get started fastTrivy (friendly defaults)
SBOM-centric pipeline, already using syftGrype
Need fine-grained conditional ignore (fix-state, etc.)Grype
Start light with a single binaryEither works

FAQ

Q. Why do Trivy and Grype report different result counts? A. Because their vulnerability DB sources differ. Trivy uses Aqua's own aggregated DB; Grype uses grype-db, which combines NVD, GitHub Advisory, and distro feeds. Package matching rules and severity classification also differ, so counts diverge. Neither is wrong.

Q. Are both free? Are there commercial versions? A. Both are free under Apache 2.0. Aqua and Anchore also sell commercial platforms with policy management, reporting, and SLAs. For CI scanning, the free versions are enough.

Q. Which severity should we start failing CI on? A. Start by failing the build on CRITICAL only, then expand to HIGH once things stabilize. If you block on MEDIUM and below from day one, false positives and unfixed CVEs will break builds so often that the team will disable the scanner.

Q. Can we scan images without an SBOM? A. Yes. trivy image or grype <image> is enough to catch vulnerabilities. Add SBOM when you need supply-chain tracking, regulatory compliance, or automated rescan.

Q. We have too many false positives. How do we cut them down? A. Use conditional suppression, not blanket ignore. In Trivy, add an expiry (exp:) in .trivyignore. In Grype, temporarily exclude only items with fix-state: not-fixed in .grype.yaml. Always track ignored items in a backlog.

확인 정보
✦ ✦ ✦
편집 검토 · Editorial Review

Nodelog는 모든 콘텐츠의 내용과 출처를 공개 전에 검토합니다. 환경(OS·버전)에 따라 결과가 달라질 수 있는 기술 정보는 공식 문서와 함께 확인하며, 검토 기준과 정정 원칙은 편집 정책에서 안내합니다. 오류를 발견하시면 이메일로 제보해 주세요 — 확인 후 신속히 정정합니다.

편집 책임 · Nodelog 기술 편집팀·발행 · ·업데이트 ·

Comments

Be the first to comment.