/툴 리뷰/Trivy vs Grype vs Docker Scout: Criteria for Choosing a CI Image Scanner
Tool ReviewsTrivyGrype

Trivy vs Grype vs Docker Scout: Criteria for Choosing a CI Image Scanner

When you scan the same image with Trivy, Grype, and Docker Scout, the counts diverge not because of accuracy but because of vulnerability DB sources and scan coverage. This post covers a situation-based elimination table, HIGH/CRITICAL gati

Trivy vs Grype vs Docker Scout: Criteria for Choosing a CI Image Scanner

Three days that started from one line: "Please add an image scan gate"

Security-team requests always come as a single line: "Please add an image vulnerability scan gate to CI." Search, though, and Trivy, Grype, and Docker Scout all claim to be "fast and accurate." Worse, when you actually run the same image through all three, the finding counts don't match. That's where most teams burn three days trying to prove "who's right."

Spoiler: that question has no answer. The three tools aren't the same thing to begin with, and the number gap is usually a difference in judgment criteria, not accuracy. So this post doesn't ask "which is better" — it asks "which one drops out in our situation." There are three axes:

  1. Scan coverage — OS packages only, or language dependencies, IaC, and secrets too?
  2. Vulnerability DB source — distro security advisories first, or NVD version matching?
  3. Exception handling and ops cost — how do you manage ignores, and does it run offline?

Identity check: these three tools are not the same category

ItemTrivyGrype (+Syft)Docker Scout
OS packagesYesYesYes
Language dependenciesYes (many ecosystems)Yes (via Syft cataloger)Yes
IaC / K8s manifestsYes (config scan)No (out of scope)No (out of scope)
Secret detectionYesNoNo
SBOMGenerate and consume (SPDX/CycloneDX)Syft generates, Grype consumesImage-based SBOM lookup
DB sourceDistro security advisories + aggregated sourcesDistro advisories + NVD and othersDocker-curated advisories
Offline operationPre-download / mirror DBPre-download / mirror DBRequires checking Docker account / service dependency
Pricing boundaryOSS CLI freeOSS CLI freeCLI free tier + org features depend on plan

Positioning in one sentence each: Grype is paired with Syft (SBOM generation = Syft, scan = Grype). That split is an advantage for teams that need to keep SBOMs as artifacts. Trivy is all-in-one, so it fits teams that want one scanner to cover images, IaC, and secrets. Docker Scout is a managed product attached to the Docker ecosystem (Desktop/Hub/CLI), so for teams already running on Hub, adoption cost is effectively near zero.

Why do the numbers differ on the same image?

Here's the core. Distros like Debian, Alpine, and Red Hat run their own Security Trackers, and they often backport patches without bumping the upstream version. The package version string stays the same, but the package is actually fixed. Distros mark these CVEs as not affected, will_not_fix, wont-fix, and similar.

  • Path that prefers distro advisories: backport is applied → CVE is excluded or classified as no fix
  • NVD version-matching path: "this package version ≤ vulnerable range" → still flagged as vulnerable

So the count gap is usually the sum of this judgment-criteria difference plus scan-coverage difference (including how language dependencies are cataloged). Don't trust someone else's benchmark table — run it on your own image and interpret the delta. If the numbers differ, check in this order: (1) different package type (OS vs language) → coverage difference (2) same package, only one tool caught it → DB source / fix-state judgment difference (3) different severity → severity scoring source difference.

Don't pick — eliminate: a situation-based decision table

SituationFirst recommendationDrop this tool, and whyWatch out
Only need single-image CI gatingAny of the three → pick by team familiarityNoneDon't spend three days comparing here. One requirement, one tool.
Need to keep/submit SBOMs as artifacts (customers/regulators)Syft+Grype or TrivyScout — too tightly coupled for pipelines that manage and sign SBOMs as independent artifactsConfirm the required format (SPDX vs CycloneDX) in the contract first
Docker Desktop/Hub-centric, developer local UX mattersDocker ScoutTrivy/Grype — they work, but you pay extra local UX, install, and training costOrg-wide policy and history depend on the plan. Check the pricing boundary first.
Air-gapped / offline (DB mirroring required)Trivy or GrypeScout — you must first verify external service and account dependencyRegister DB mirror refresh as an ops item (stale DB makes scans meaningless)
Cover IaC and secrets with one toolTrivyGrype/Scout — those scopes are out of designBundling into one tool makes failure isolation hard. Prefer separate jobs.
Too many image vulns; the gate never sticks(Tool-agnostic) replace the base image firstThere is a real zone where shrinking the surface is faster than tuning the scanner

Using two is sometimes the right call. Syft to emit SBOMs as artifacts, Trivy for gating satisfies both supply-chain requirements and the gate. You do have to explicitly accept the tradeoff of roughly doubling CI time.

Copy-paste production config + failure branches

One-liner scans for all three tools locally

Bash
# 세 도구 모두 옵션이 버전마다 다르므로 --version / --help로 먼저 확인
trivy image myapp:1.0

syft myapp:1.0 -o cyclonedx-json > sbom.json && grype sbom:sbom.json

docker scout cves myapp:1.0

A healthy result is a vulnerability summary table (package / installed version / CVE / severity / fixed version). Record the count and elapsed time here. That record is your evidence, not someone else's table. If output is empty, it's often a mistyped image tag or a DB download failure — check the exit code and stderr first.

GitHub Actions: fail only on HIGH/CRITICAL

YAML
- name: Trivy gate
  run: |
    trivy image --severity HIGH,CRITICAL \
      --ignore-unfixed --exit-code 1 myapp:${{ github.sha }}
YAML
- name: Grype gate
  run: |
    syft myapp:${{ github.sha }} -o cyclonedx-json > sbom.json
    grype sbom:sbom.json --fail-on high
YAML
- name: Scout gate
  run: |
    docker scout cves --exit-code \
      --only-severity critical,high myapp:${{ github.sha }}

In all three cases, exit code 1 is a gate failure. A staged rollout — block CRITICAL first, treat HIGH as a warning — is the realistic path.

Exceptions: an ignore file left unattended becomes debt

TEXT
# .trivyignore
# CVE-2024-XXXXX
# 사유: 사용하지 않는 코드 경로 / 담당: dhson / 만료: 2026-09-30
CVE-2024-XXXXX
YAML
# .grype.yaml
ignore:
  - vulnerability: CVE-2024-XXXXX
    package:
      name: libfoo
    fix-state: not-fixed   # 조건부 예외: 패키지·fix 상태까지 지정 가능

Docker Scout is closer to policy/dashboard-based exceptions than files. That's better for org-wide control, but you have to accept that the rationale for exceptions won't live in code-review history.

The format differs; the rule does not. If an exception has no reason, owner, or expiry, nobody can delete it six months later. Add a job that periodically pulls expired exceptions for review.

Three failure branches you will hit

① DB download rate limit / offline failure Registry pull limits or an air-gapped network can fail the entire scan. The fix is cache + pre-fetch.

Bash
# 예: DB만 먼저 받아 캐시에 적재 → 이후 --skip-db-update로 스캔
trivy image --download-db-only
trivy image --skip-db-update myapp:1.0

In CI, cache the DB directory with actions/cache or similar; in an air-gapped network, mirror the DB to an internal registry. If the mirror stops updating, scans still pass but mean nothing, so put the refresh interval on the monitoring list.

② Pipeline permanently fails because there is no fixed version A CVE the distro marked will_not_fix never goes away no matter how much you update. That's when you use --ignore-unfixed (Trivy) or a fix-state filter (Grype) — but turning it on unconditionally hides real risk. Use this rule: the gate (merge block) only includes fixable issues — the "go fix it" instruction has to be actionable. The report (weekly issues) includes everything — the risk itself still has to be visible.

③ Replacing the base image is faster than tuning the scanner If you're surviving by adding ignore entries one by one, you may be pointed the wrong way. The rule is simple: once ignore entries exceed five, suspect the base image. Switching to distroless, slim, or alpine, and splitting build stages (strip compile tools from the final image) shrinks the vulnerability surface itself — and that zone is clearly faster than tuning.

Adoption cost math and three things to do this week

CI time is real money. Start with this formula:

CODE
증가 CI분/월 = (스캔 소요 초 ÷ 60) × 일 빌드 수 × 근무일

Example: 40-second scan, 20 builds/day, 20 working days → about 267 minutes/month (example — varies by environment). The biggest variable is whether the vulnerability DB is cached. Without a cache, every build re-downloads tens to hundreds of MB of DB, and that time can exceed the scan itself. Measure before and after cache, plug into the formula, and you'll usually conclude that adding a cache is the first priority.

Draw the paid-conversion line in advance too. A few repos, one team, gating only — OSS CLI is enough. Once you need org-wide policy rollout, vuln history/trend dashboards, and audit evidence, you're in the phase of comparing build-it-yourself cost vs a paid plan. Confirm the exact free scope and pricing in each vendor's official docs.

Three things to do this week. First, run the three one-liners on your own image today and record the counts and elapsed times. Second, find the row in the decision table that matches your situation, eliminate, and lock in what's left. Third, open one HIGH/CRITICAL gating PR.

Picking a scanner is not a taste contest; it's a constraints check. Offline? Must submit SBOMs? Need IaC coverage? Answer those three and the field usually collapses to one. Instead of spending three days comparing numbers, write down the constraints, eliminate, and open the PR today. A gate that's on today is always safer than the perfect tool.

FAQ

Q. Which is more accurate, Trivy or Grype? A. When results diverge on the same image, it's usually judgment criteria, not accuracy. A path that prefers distro security advisories (backports, will_not_fix) and a path that matches NVD versions will judge the same package differently. Run both on your own image, then classify each delta as a package-type difference or a fix-state judgment difference.

Q. Can I always turn on --ignore-unfixed? A. For the gate (merge block), yes — that's realistic. If a CVE with no fixed version permanently fails the pipeline, developers have nothing they can do. For weekly reports and security reviews, turn it off and look at everything. Leave it on unconditionally and real risk disappears from view.

Q. Can you scan images on an air-gapped network? A. Yes. Both Trivy and Grype support pre-downloading the vulnerability DB or mirroring it internally. The key is managing the mirror refresh interval as an ops item. A stale DB means scans pass but mean nothing. For Docker Scout, first verify the external service and account dependency.

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

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

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

Comments

Be the first to comment.