Trivy 컨테이너 이미지 취약점 스캔 완벽 가이드 2026: CI/CD 통합과 VEX 관리

Trivy v0.71.0으로 컨테이너 이미지 취약점을 스캔하고 GitHub Actions·GitLab CI 파이프라인에 게이트로 걸어두는 실전 방법. SBOM/VEX로 오탐을 관리하고 Kubernetes 런타임까지 지속 감시하는 아키텍트 관점 가이드.

Trivy 컨테이너 스캔 가이드 2026

업데이트: 2026년 8월 9일

Trivy는 컨테이너 이미지·파일시스템·IaC·Kubernetes 클러스터에서 알려진 취약점, 시크릿 노출, 잘못된 구성을 단일 바이너리로 스캔하는 오픈소스 스캐너입니다. 2026년 6월 1일 공개된 v0.71.0은 CycloneDX 1.6 SBOM 형식과 리포지터리 내부 VEX 문서 로딩을 지원하며, .NET 애플리케이션 취약점 탐지까지 커버 범위를 넓혔습니다. 저는 하이퍼스케일러에서 매일 수만 개의 이미지를 검사하는 파이프라인을 설계하는데, 위협 모델을 세울 때마다 첫 번째로 던지는 질문은 항상 같습니다. "이 이미지가 침해되면 무엇이 먼저 무너지는가?" 이 글은 그 질문에 답하기 위해 Trivy를 CI/CD에 심는 실전 절차를 정리합니다.

  • Trivy v0.71.0(2026-06-01)은 단일 Go 바이너리로 컨테이너·파일시스템·Git·Kubernetes·IaC를 모두 스캔하며, Apache-2.0 라이선스로 GitHub 스타 36,000개 이상을 보유한 사실상 표준 오픈소스 스캐너입니다.
  • CI 게이트는 --severity HIGH,CRITICAL --exit-code 1로 배포를 중단시키는 강제 정책과, 개발 브랜치에서는 MEDIUM 이하를 리포트만 하는 완화 정책을 분리해 설계해야 합니다.
  • 오탐 관리는 .trivyignore 파일에 소유자·이유·재검토 날짜 3요소를 반드시 주석으로 남기고, 릴리스 아티팩트 수준에서는 OpenVEX 문서로 승격시켜야 감사 가능한 상태가 됩니다.
  • Grype보다 30~40% 느리지만 IaC·시크릿·SBOM까지 커버하는 Trivy와, 이미지 CVE만 빠르게 뽑는 Grype를 이중 엔진으로 조합하는 것이 2026년 프로덕션 표준 구성입니다.
  • Kubernetes 클러스터에서는 trivy k8s와 Trivy Operator(어드미션 컨트롤러 연동)로 런타임 이미지까지 지속 감시하고, GitOps 도구와 결합해 재스캔 주기를 자동화해야 합니다.
  • 스캔은 어디까지나 탐지 계층이므로, 하드닝된 베이스 이미지(distroless, chainguard)와 최소 권한 원칙이 선행되지 않으면 리포트만 두꺼워집니다.

Trivy란 무엇이며 왜 2026년 표준이 되었는가

Trivy는 Aqua Security가 오픈소스로 공개한 취약점 스캐너로, 단일 실행 파일 하나에 컨테이너 이미지 스캔, 파일시스템 스캔, Git 리포지터리 스캔, Kubernetes 클러스터 스캔, IaC(Terraform/CloudFormation/Kubernetes 매니페스트) 스캔, 시크릿 탐지, 라이선스 검사 기능을 모두 담고 있습니다. 아키텍트 관점에서 이 "단일 바이너리 다목적 스캐너"라는 특성이 왜 중요한지 먼저 짚고 넘어가야 합니다.

공급망 공격 관점에서 컨테이너 이미지의 블래스트 레이디어스(blast radius)는 대체로 세 층으로 구성됩니다. 첫째, 베이스 이미지에 포함된 OS 패키지. 둘째, 애플리케이션이 명시적으로 선언한 의존성(package.json, go.mod, pom.xml 등). 셋째, 빌드 과정에서 부수적으로 딸려온 트랜지티브 바이너리와 개발 툴체인 잔여물. Grype 같은 CVE 전용 스캐너는 첫째와 둘째만 잘 잡지만, Trivy는 세 층 전체와 함께 시크릿·IaC 취약점까지 한 번에 훑기 때문에 사고 후 리포트를 만들 때 "무엇이 이미지에 있었는지" 하나의 도구로 답할 수 있습니다. 이 감사 가능성이 저희 팀이 Trivy를 기본 표준으로 정착시킨 결정적 이유입니다.

또 하나 중요한 점은 CNCF Sandbox 프로젝트로 격상되면서 프로덕션 채택률이 급증했다는 것입니다. GitHub 스타 36,000개 이상, Apache-2.0 라이선스, 그리고 Aqua가 상용 제품(Aqua Enterprise)의 스캔 엔진으로 동일 코드베이스를 유지하기 때문에 커뮤니티 이슈가 상용급 속도로 해소됩니다. 관련된 런타임 탐지 계층은 eBPF 기반 리눅스 런타임 보안 가이드(Falco와 Tetragon)에서 다뤘으니, 이미지 스캔은 사전 예방이고 런타임 탐지는 사후 대응이라는 두 축을 함께 배치하시길 권합니다.

Trivy v0.71.0의 주요 변경사항과 업그레이드 포인트

2026년 6월 1일 공개된 Trivy v0.71.0 공식 릴리스 노트에서 가장 눈여겨봐야 할 변경사항은 세 가지입니다.

1. VEX 문서 로딩 버그 수정

이전 버전에서는 .vex/ 디렉터리를 리포지터리 루트에 두면 스캔 시 인식되지 않는 문제가 있었습니다. v0.71.0에서 fix(vex): load VEX documents from within the repository directory 커밋으로 이 문제가 해결되었습니다. GitOps 워크플로우에서 SBOM과 VEX를 함께 커밋해 두는 팀이라면 반드시 업그레이드하세요. 이전 버전에서는 조용히 무시되었기 때문에 "오탐 억제가 왜 안 되지?" 하고 몇 시간을 낭비할 수 있습니다.

2. CycloneDX 1.6 SBOM 지원

CycloneDX 1.5까지는 취약점 정보와 컴포넌트 관계 표현에 제약이 있었지만, 1.6에서는 evidence.identity 필드와 ml-model 컴포넌트 타입이 추가되어 LLM 모델까지 SBOM으로 표현할 수 있게 되었습니다. 온프렘 AI 서빙 이미지를 스캔한다면 이 부분이 중요합니다.

3. .NET 취약점 탐지 확장

C# 진영에서는 오랫동안 Snyk와 WhiteSource가 사실상 표준이었지만, v0.71.0부터 .deps.jsonpackages.lock.json 파싱이 견고해져 .NET 8·9 이미지 스캔 정확도가 눈에 띄게 올라갔습니다. Windows Container를 프로덕션에 배포하는 팀에는 반가운 소식입니다.

Trivy 설치와 첫 컨테이너 이미지 스캔

Trivy는 배포판별 패키지, 정적 바이너리, 도커 이미지, Homebrew 등 여러 경로로 설치할 수 있습니다. CI 파이프라인에서는 도커 이미지를, 로컬 개발 환경에서는 패키지 매니저를 쓰는 것이 관리 오버헤드가 가장 낮습니다.

RHEL·Rocky·AlmaLinux 계열

# Aqua Security 공식 RPM 리포지터리 등록
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
trivy --version
# Version: 0.71.0
# Vulnerability DB: schema=2, updated=...

Debian·Ubuntu 계열

sudo apt-get install -y wget apt-transport-https 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 $(lsb_release -cs) main" \
  | sudo tee /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install -y trivy

첫 이미지 스캔

# nginx 공식 이미지를 스캔 (처음 실행 시 취약점 DB를 자동 다운로드)
trivy image nginx:1.27

# 심각도가 HIGH 또는 CRITICAL인 항목만 출력하고, 하나라도 있으면 exit code 1 반환
trivy image \
  --severity HIGH,CRITICAL \
  --exit-code 1 \
  --ignore-unfixed \
  nginx:1.27

여기서 --ignore-unfixed는 실무에서 반드시 이해해야 할 옵션입니다. 취약점이 존재하지만 업스트림에서 아직 패치가 배포되지 않은 CVE는 사용자가 "지금 당장" 대응할 방법이 없습니다. 개발 초기에는 이걸 걸어두어야 팀이 배포 가능한 항목에 집중할 수 있습니다. 다만 릴리스 게이트에서는 이 플래그를 빼고 trivy image --format sarif로 SARIF 리포트를 생성해 감사 로그에 남겨야 합니다.

Trivy vs Grype vs Clair 비교: 무엇을 언제 쓸 것인가

"Trivy 하나면 충분한가?"는 팀마다 답이 다릅니다. 저는 아키텍처 리뷰에서 항상 이 세 도구의 트레이드오프를 표로 정리해 놓고 팀이 자기 상황에 맞게 고르도록 합니다.

항목TrivyGrypeClair
개발사Aqua SecurityAnchoreRed Hat / Quay
배포 형태단일 CLI 바이너리단일 CLI 바이너리서버 + API
이미지 스캔 속도보통가장 빠름 (Trivy 대비 -30~40%)느림 (네트워크 왕복 포함)
IaC 스캔지원 (Terraform, K8s YAML, CloudFormation)미지원미지원
SBOM 생성CycloneDX 1.6, SPDXCycloneDX, SPDX (Syft 연동)미지원
시크릿 스캔지원미지원미지원
Kubernetes 클러스터 스캔지원 (trivy k8s, Trivy Operator)제한적미지원
운영 오버헤드낮음가장 낮음높음 (Postgres·업데이트 잡 필요)

실무 권장 구성은 이렇습니다. 로컬 개발자 머신과 PR 게이트에서는 Trivy 하나로 통일해 러닝 커브를 낮추고, 프로덕션에 배포되는 최상위 레이어 이미지(공용 베이스, 인터넷 노출 서비스)에는 Grype를 두 번째 의견 스캐너로 병행합니다. 두 스캐너의 결과가 크게 갈리면 대개 취약점 DB 업데이트 시차나 CPE 매칭 방식 차이 때문이므로, 두 리포트를 자동으로 diff해서 알리는 노티피케이션을 붙여두면 오탐 튜닝에 큰 도움이 됩니다. Clair는 Quay 레지스트리와 결합해 쓸 때만 실질적 이점이 있습니다.

CI/CD 파이프라인에 Trivy를 통합하는 방법

스캔은 개발자 로컬이 아니라 CI에서 강제될 때만 의미가 있습니다. GitHub Actions와 GitLab CI 두 가지 표준 구성을 실전 코드로 정리하겠습니다. 공식 예제와 옵션은 Trivy 공식 CI/CD 통합 문서에도 상세히 안내되어 있습니다.

GitHub Actions: PR 게이트와 SARIF 업로드

name: Container Security
on:
  pull_request:
    paths: ['Dockerfile', 'src/**', '.github/workflows/**']
  push:
    branches: [main]

jobs:
  trivy-scan:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      security-events: write   # SARIF 업로드에 필요
    steps:
      - uses: actions/checkout@v4

      - name: Build image
        run: docker build -t app:${{ github.sha }} .

      - name: Trivy scan (block on HIGH/CRITICAL)
        uses: aquasecurity/[email protected]
        with:
          image-ref: 'app:${{ github.sha }}'
          format: 'sarif'
          output: 'trivy-results.sarif'
          severity: 'HIGH,CRITICAL'
          exit-code: '1'
          ignore-unfixed: true
          vuln-type: 'os,library'

      - name: Upload SARIF to GitHub Security
        if: always()   # 실패해도 리포트는 올려야 감사가 가능
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: 'trivy-results.sarif'

세 가지 디자인 결정에 주목하세요. 첫째, if: always()로 스캔이 실패해 잡이 죽어도 SARIF 리포트는 GitHub Security 탭에 올라갑니다. 둘째, permissions를 최소 권한(contents: read)으로 명시해 워크플로우 자체의 블래스트 레이디어스를 좁힙니다. 셋째, vuln-type: 'os,library'로 애플리케이션 의존성과 OS 패키지를 모두 잡고 라이선스 스캔은 별도 잡으로 분리합니다.

GitLab CI: 캐시와 컨테이너 스캔 리포트

stages:
  - build
  - security

variables:
  TRIVY_CACHE_DIR: .trivycache/
  TRIVY_NO_PROGRESS: "true"

container_scanning:
  stage: security
  image:
    name: aquasec/trivy:0.71.0
    entrypoint: [""]
  cache:
    key: trivy-db-${CI_COMMIT_REF_SLUG}
    paths:
      - .trivycache/
  script:
    - trivy image --download-db-only --cache-dir $TRIVY_CACHE_DIR
    - trivy image
        --cache-dir $TRIVY_CACHE_DIR
        --exit-code 0
        --severity MEDIUM,LOW,UNKNOWN
        --format template
        --template "@contrib/gitlab.tpl"
        --output gl-container-scanning-report.json
        $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - trivy image
        --cache-dir $TRIVY_CACHE_DIR
        --exit-code 1
        --severity HIGH,CRITICAL
        --ignore-unfixed
        $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  artifacts:
    reports:
      container_scanning: gl-container-scanning-report.json

이 파이프라인의 핵심은 두 번 스캔한다는 점입니다. 첫 번째 실행은 낮은 심각도까지 포함해 GitLab의 컨테이너 스캐닝 리포트에 데이터를 채워 넣고(파이프라인은 실패시키지 않음), 두 번째 실행은 HIGH/CRITICAL만 확인해 실제 배포 게이트로 작동합니다. 개발 팀은 대시보드에서 전체 노출을 보되, 배포는 실제로 조치 가능한 항목에 대해서만 막힙니다.

SBOM과 VEX로 오탐과 공급망을 관리하는 법

스캐너를 켜두고 몇 주가 지나면 반드시 마주치는 문제가 있습니다. 리포트에 나오는 CVE 중 상당수가 "실제로는 우리 시스템에서 활용 불가능한" 것들이라는 사실입니다. 이걸 그냥 무시하면 리포트가 노이즈로 가득 차 진짜 위험이 묻히고, 그렇다고 개별 스캔마다 매번 필터링하면 지식이 휘발됩니다. 해답은 SBOM과 VEX를 릴리스 아티팩트로 승격시키는 것입니다.

.trivyignore로 시작하기

# .trivyignore — 리포지터리 루트에 두는 가장 단순한 오탐 억제 파일
# 형식: CVE-ID 한 줄에 하나, # 뒤는 주석

# 소유자: [email protected]
# 이유: golang.org/x/net 취약점은 클라이언트 코드에서 미사용
# 재검토: 2026-11-01
CVE-2025-58185

# 소유자: platform-team
# 이유: 컨테이너 내부에서 SSH 미사용, glibc gethostbyname 경로 도달 불가
# 재검토: 2026-10-15
CVE-2026-1234

여기서 "소유자, 이유, 재검토 날짜" 세 요소가 없는 .trivyignore는 곧 아무도 정리하지 못하는 쓰레기가 됩니다. 저는 PR 리뷰 훅으로 이 세 필드가 주석에 있는지 grep으로 강제하고, 재검토 날짜가 지난 항목은 다음 스프린트 백로그에 자동으로 올리는 스크립트를 붙여둡니다.

OpenVEX 문서로 승격

여러 이미지·여러 팀에 걸쳐 같은 CVE를 무시해야 한다면 .trivyignore 파일은 곧 확장성 한계에 부딪힙니다. 이 시점에 필요한 것이 VEX(Vulnerability Exploitability eXchange) 문서입니다. OpenVEX는 "이 특정 제품 X는 이 특정 CVE Y에 영향받지 않는다"는 진술을 서명 가능한 JSON 형식으로 표현한 표준입니다. Trivy VEX 파일 공식 문서에 스키마 전체가 정리되어 있습니다.

{
  "@context": "https://openvex.dev/ns/v0.2.0",
  "@id": "https://example.com/vex/app-v1.4.2",
  "author": "Aisha Okonkwo ",
  "timestamp": "2026-08-09T12:00:00Z",
  "version": 1,
  "statements": [
    {
      "vulnerability": { "name": "CVE-2025-58185" },
      "products": [
        {
          "@id": "pkg:oci/app@sha256:abc123...",
          "subcomponents": [
            { "@id": "pkg:golang/golang.org/x/[email protected]" }
          ]
        }
      ],
      "status": "not_affected",
      "justification": "vulnerable_code_not_in_execute_path",
      "impact_statement": "클라이언트 코드에서 x/net/html 파서를 호출하지 않음"
    }
  ]
}
# VEX 문서를 스캔에 적용
trivy image \
  --vex ./vex/app-v1.4.2.openvex.json \
  --format json \
  --output scan.json \
  registry.example.com/app:v1.4.2

Trivy v0.71.0부터 리포지터리 내부 .vex/ 디렉터리의 문서를 자동으로 로드하므로, 릴리스 태그마다 SBOM(CycloneDX) + VEX(OpenVEX) 한 쌍을 GitHub Release 아티팩트로 첨부해두는 워크플로우가 이제 실무에서 완전히 작동합니다. 감사관이 "이 릴리스에 대해 스캐너가 왜 이 CVE를 무시했나?"를 물었을 때 서명된 JSON 한 파일로 답할 수 있다는 것, 이것이 .trivyignore와의 근본적 차이입니다.

Kubernetes 클러스터와 어드미션 컨트롤러 스캔

이미지 스캔은 빌드 시점 방어지만, 이미지가 배포된 후 새로 공개되는 CVE는 별도로 감시해야 합니다. Trivy는 이 지속 감시를 두 가지 방법으로 지원합니다.

trivy k8s: 원샷 클러스터 감사

# 현재 kubeconfig 컨텍스트의 모든 워크로드 스캔
trivy k8s --report summary cluster

# 특정 네임스페이스만, HIGH 이상만
trivy k8s \
  --namespace production \
  --severity HIGH,CRITICAL \
  --report all \
  --format json \
  --output k8s-scan.json

# 하나의 워크로드만
trivy k8s deployment/payment-api -n production

운영 팀 온보딩 첫날에 trivy k8s --report summary cluster를 돌려서 나오는 리포트를 함께 보는 것을 강력히 권합니다. 예상보다 훨씬 더 많은 것이 나와 팀이 우선순위를 다시 잡게 될 겁니다.

Trivy Operator: 지속 감시와 어드미션 게이트

더 지속 가능한 접근은 Trivy Operator를 클러스터에 설치해 CRD(VulnerabilityReport, ConfigAuditReport, ExposedSecretReport)로 결과를 축적하는 것입니다. Prometheus와 Grafana에서 바로 대시보드를 그릴 수 있고, OPA/Gatekeeper나 Kyverno 정책과 결합하면 취약점 리포트를 조건으로 어드미션을 막을 수 있습니다.

# Helm으로 Trivy Operator 설치
helm repo add aqua https://aquasecurity.github.io/helm-charts/
helm install trivy-operator aqua/trivy-operator \
  --namespace trivy-system \
  --create-namespace \
  --set trivy.severity=HIGH,CRITICAL \
  --set operator.scanJobsConcurrentLimit=5

# 생성된 취약점 리포트 확인
kubectl get vulnerabilityreports -A
kubectl describe vulnerabilityreport -n production \
  deployment-payment-api-6d4b8f9c

여기에 Kyverno 정책 하나를 얹으면 "CRITICAL 취약점이 3개 이상 있는 이미지는 배포 불가"를 강제할 수 있습니다. 이렇게 되면 개발자는 CI에서 뿐만 아니라 클러스터 진입 시점에도 게이트를 통과해야 하고, 릴리스 이후 새로 공개된 CVE에 대해서도 다음 재스캔 주기(기본 6시간)마다 상태가 갱신됩니다. 침입 탐지 계층과의 통합은 auditd 실전 가이드에서 다룬 감사 로그와 결합해 SIEM에 흘려보내면 완결됩니다.

하드닝된 컨테이너 이미지를 만드는 실전 전략

스캐너가 CVE 0개를 리포트한다고 안전한 이미지가 되는 건 아닙니다. 저는 신입 엔지니어에게 항상 같은 말을 합니다. "스캐너는 이미 알려진 문제를 찾을 뿐, 이미지 자체의 공격 표면을 줄여주진 않습니다." 진짜 방어는 이미지 설계 단계에서 시작됩니다.

베이스 이미지 선택 기준

  • distroless(gcr.io/distroless): 셸조차 없는 최소 런타임. 침해 시 공격자가 실행할 수 있는 것이 극도로 제한됩니다.
  • Chainguard Images(cgr.dev): 매일 리빌드되어 CVE 0개를 목표로 유지되는 상용 이미지. 무료 티어에서도 latest 태그는 사용 가능합니다.
  • Wolfi: Chainguard가 만든 리눅스 배포판. glibc 대신 musl 기반이 아니라 glibc 기반이라 호환성 문제가 적습니다.
  • Alpine: 가볍지만 musl libc와 BusyBox 때문에 미묘한 호환성 이슈가 있습니다. Go/Rust 정적 바이너리에는 좋지만 파이썬·자바 워크로드에는 신중히 선택하세요.

멀티스테이지 빌드로 공격 표면 축소

# Stage 1: 빌드 — 툴체인은 여기에만 존재
FROM golang:1.24 AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app ./cmd/api

# Stage 2: 런타임 — 셸도, 패키지 매니저도 없음
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=builder /app /app
USER nonroot:nonroot
EXPOSE 8080
ENTRYPOINT ["/app"]

이 패턴의 효과는 극적입니다. golang:1.24 이미지 하나만으로 스캔하면 대개 200~400개의 CVE가 뜨지만, distroless 최종 이미지는 통상 0~5개 수준입니다. 이유는 단순합니다. 최종 이미지에는 GCC, 셸, apt, 패키지 매니저, 문서, 사람 언어 로케일이 모두 빠져 있기 때문입니다.

이미지 서명과 공급망 검증

Sigstore Cosign으로 이미지에 서명하고, Trivy Operator의 어드미션 정책에서 서명 없는 이미지를 거부하면 공급망 공격의 마지막 한 층까지 방어할 수 있습니다. 서명은 keyless 모드(OIDC 기반)를 쓰면 개인 키 관리 부담 없이 GitHub Actions 워크플로우 정체성으로 서명이 가능합니다.

# GitHub Actions에서 keyless 서명
- name: Install Cosign
  uses: sigstore/cosign-installer@v3

- name: Sign image
  env:
    COSIGN_EXPERIMENTAL: "1"
  run: |
    cosign sign --yes \
      registry.example.com/app@${{ steps.build.outputs.digest }}

# 서명 검증 (배포 파이프라인에서)
cosign verify \
  --certificate-identity-regexp="https://github.com/example/.*" \
  --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
  registry.example.com/app@sha256:abc123...

자주 묻는 질문

Trivy와 Grype 중 무엇을 선택해야 하나요?

이미지 CVE만 빠르게 뽑아야 한다면 Grype가 30~40% 더 빠릅니다. 하지만 실무에서는 컨테이너 이미지 외에도 Kubernetes 매니페스트, Terraform, 시크릿 탐지가 함께 필요한 경우가 대부분이므로 Trivy를 기본으로 채택하고, 최상위 프로덕션 이미지에만 Grype를 두 번째 의견으로 병행하는 이중 엔진 구성이 2026년 표준입니다.

Trivy는 무료인가요?

네, Trivy는 Apache-2.0 라이선스 오픈소스입니다. Aqua Security가 상용 제품 Aqua Enterprise를 별도 판매하지만, 스캔 엔진 자체는 동일 코드베이스이므로 오픈소스 사용자도 상용 수준의 정확도를 얻습니다. 사내 프로덕션과 상업적 사용도 라이선스 제한 없이 가능합니다.

Trivy 취약점 DB는 얼마나 자주 업데이트되나요?

공식 취약점 DB는 하루 두 번(약 6시간 간격) 갱신되어 GitHub Container Registry의 OCI 아티팩트로 배포됩니다. CI 환경에서는 --cache-dir로 캐시하되 매번 --download-db-only로 델타 업데이트만 받도록 구성하면, 첫 실행 이후 다운로드 부담이 수 MB 수준으로 떨어집니다.

스캐너를 우회하는 방법이 있나요?

기술적으로는 이미지 레이어에 취약점 DB에 등록되지 않은 커스텀 바이너리를 심으면 CVE 기반 스캐너는 이를 잡지 못합니다. 이 때문에 스캐너 외에 시크릿 스캔, 라이선스 검사, 이미지 서명 검증, 그리고 런타임 이상 행위 탐지를 함께 배치하는 심층 방어가 필수입니다.

CI가 CRITICAL 취약점을 만나면 무조건 실패해야 하나요?

완벽한 세계에서는 그렇지만, 현실에서는 업스트림 패치가 없는 CRITICAL CVE도 존재합니다. 저는 --ignore-unfixed로 조치 가능한 항목만 게이트에 걸고, 조치 불가능한 CRITICAL은 별도 위험 등록부(risk register)에 자동으로 티켓을 열도록 파이프라인을 구성합니다. "무조건 차단"보다 "무조건 가시화"가 실제 조직에서 더 잘 작동합니다.

Aisha Okonkwo
저자 소개 Aisha Okonkwo

Infrastructure security architect at a hyperscaler. Spends her days on Zero Trust, secrets management, and yelling at unencrypted backups.