Trivy pe Linux în 2026: Scanare Vulnerabilități pentru Containere, IaC și Pipeline-uri DevSecOps

Ghid practic Trivy pe Linux în 2026: instalare, scanare imagini Docker și IaC, integrare CI/CD, Trivy Operator pentru Kubernetes și SBOM CycloneDX pentru compliance.

Trivy pe Linux 2026: Ghid Complet DevSecOps

Actualizat: 2 septembrie 2026

Trivy este un scanner open-source dezvoltat de Aqua Security care detectează vulnerabilități cunoscute (CVE), configurări greșite, secrete expuse și probleme de licențiere în imagini de container, filesystem-uri, repositoare Git, manifeste Kubernetes și șabloane Terraform, dintr-un singur binar, fără server sau bază de date de administrat. În 2026, Trivy a devenit standardul de facto pentru „shift-left security" în echipele DevSecOps care rulează pe Linux, cu peste 35.000 de stele pe GitHub și integrare nativă în GitHub Actions, GitLab CI și cluster-e Kubernetes prin Trivy Operator.

  • Trivy scanează într-un singur pas pachetele OS (Alpine, Debian, RHEL, Ubuntu), dependințele de aplicație (npm, pip, Go, Cargo, Maven), IaC (Terraform, CloudFormation, Kubernetes YAML), secrete embed-uite și licențe.
  • Pentru a bloca un build pe CVE critice folosește trivy image --exit-code 1 --severity HIGH,CRITICAL --ignore-unfixed, combinația care taie zgomotul CVE-urilor fără patch upstream.
  • Trivy Operator rulează în interiorul cluster-ului Kubernetes și rescanează workload-urile continuu, materializând rezultatele ca resurse custom (VulnerabilityReport, ConfigAuditReport, RbacAssessmentReport).
  • Comparativ cu Grype, Trivy pierde 30–40 % viteză pe scanarea pură de imagine, dar acoperă IaC, secrete și K8s, motiv pentru care majoritatea echipelor îl aleg drept scanner principal și lasă Grype pentru cross-check.
  • Fișierul .trivyignore și adnotările .trivyignore.yaml permit excepții per-CVE cu dată de expirare, ceea ce previne acumularea permanentă a datoriei de securitate.
  • Generarea automată de SBOM în format CycloneDX sau SPDX din trivy image --format cyclonedx satisface cerințele Executive Order 14028 și ale NIS2 pentru trasabilitatea componentelor.

Ce este Trivy și ce scanează

Trivy e un binar Go compilat static care rulează local sau într-un container fără dependințe externe. La primul trivy image, tool-ul descarcă baza de date de vulnerabilități (aproximativ 100 MB, actualizată la 6 ore) și o cache-uiește în ~/.cache/trivy. De acolo, poate răspunde la orice scanare în câteva secunde.

Onest, primul lucru care mi-a plăcut la Trivy când l-am introdus în pipeline-ul unui client fintech a fost tocmai lipsa serverului. Fără bază de date de gestionat, fără licențe, fără agent. Doar un binar și un cache.

În 2026, Trivy 0.58+ acoperă cinci tipuri distincte de artefacte pe care majoritatea echipelor le trec printr-un pipeline DevSecOps:

  • Pachete OS: Alpine apk, Debian/Ubuntu dpkg, RHEL/Fedora rpm, SUSE zypper, Amazon Linux, Wolfi, Chainguard, Rocky, Alma.
  • Dependințe de aplicație: package-lock.json, yarn.lock, Pipfile.lock, poetry.lock, go.mod, Cargo.lock, pom.xml, Gemfile.lock, composer.lock.
  • Infrastructure as Code: Terraform HCL, CloudFormation JSON/YAML, Dockerfile, Kubernetes YAML, Helm chart-uri, Azure ARM, Ansible playbook-uri.
  • Secrete: chei AWS/GCP/Azure, token-uri GitHub/GitLab/Slack, certificate private PEM, string-uri de conexiune bază de date embed-uite în layer-e de imagine.
  • Licențe: detectează GPL, AGPL, LGPL, MIT, Apache-2.0 din metadatele pachetelor și ale fișierelor sursă pentru compliance software licensing.

Această acoperire largă e motivul pentru care Trivy este de multe ori descris ca „unified security scanner". În loc să compui un lanț de tool-uri (Snyk pentru dependințe, Checkov pentru IaC, Gitleaks pentru secrete), un singur binar acoperă tot conveyor-ul, cu output consistent JSON, SARIF sau CycloneDX. Documentația oficială din Trivy.dev menține matricea completă de suport pe distribuții și limbaje.

Instalare Trivy pe Linux (Debian, RHEL, Arch)

Pentru rulare la nivel de dezvoltator sau CI runner Linux, instalarea prin pachet nativ este preferată, se actualizează automat cu apt/dnf și include verificare de semnătură. Pe Debian/Ubuntu:

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
trivy --version

Pe RHEL, Rocky, Alma sau Fedora:

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

Pe Arch: sudo pacman -S trivy. Pentru CI runner-e efemere unde nu vrei să bat-uiești cache-ul repository-ului, folosește direct scriptul oficial de instalare. Este singurul mod recomandat de proiect pentru mediile fără persistență de disc:

curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \
  | sh -s -- -b /usr/local/bin v0.58.0

La prima rulare, forțează un download offline al bazei de date pentru a pre-încălzi cache-ul. E util în build-uri paralele care ar suprasolicita mirror-ul:

trivy image --download-db-only
trivy image --download-java-db-only

Cum scanezi o imagine Docker cu Trivy

Scanarea unei imagini locale sau remote e comanda pe care o vei rula cel mai des. Trivy comunică direct cu daemon-ul Docker (sau containerd, podman, CRI-O) și, dacă nu găsește imaginea local, o pull-uiește din registru. Sintaxa minimă:

trivy image nginx:1.27.3-alpine

Output-ul default listează CVE-urile grupate pe pachet, cu severitate, versiune fix și link către CVE. Pentru un pipeline CI, ai nevoie de trei flag-uri esențiale care transformă tool-ul dintr-un observator într-un gate:

trivy image \
  --severity HIGH,CRITICAL \
  --ignore-unfixed \
  --exit-code 1 \
  --format sarif \
  --output trivy-report.sarif \
  myregistry.io/api:${CI_COMMIT_SHA}

Fiecare flag rezolvă o problemă concretă:

  • --severity HIGH,CRITICAL: filtrează zgomotul. Vulnerabilitățile LOW și MEDIUM sunt sute per imagine base, iar blocarea pe ele va face echipa să dezactiveze scanarea în două săptămâni.
  • --ignore-unfixed: exclude CVE-urile fără patch upstream. Nu are sens să blochezi build-ul pentru un CVE unde nu există nimic de făcut.
  • --exit-code 1: face ca pipeline-ul CI să eșueze deterministic. Fără el, scanarea raportează, dar nu oprește deployment-ul.
  • --format sarif: output-ul SARIF este ingerat direct de GitHub Advanced Security, GitLab Security Dashboard și Sonatype, pentru vizualizare pe PR.

Un truc pe care îl folosesc în audit-urile mele: rulează trivy image --scanners vuln,secret,misconfig pentru a combina scanarea de CVE cu detectarea de secrete embed-uite și configurări proaste ale Dockerfile-ului. Am pierdut socoteala câte chei AWS am găsit lăsate într-un layer intermediar de docker build, doar în ultimul an.

Scanare IaC, secrete și SBOM

Trivy nu se limitează la containere. Pentru un repository cu Terraform și manifeste Kubernetes, comanda trivy config analizează statistic fișierele și le compară cu regulile din trivy-checks, o colecție deschisă cu peste 400 de politici scrise în Rego (OPA).

# Scanează directorul curent pentru misconfigurări IaC
trivy config --severity HIGH,CRITICAL ./infra/

# Scanează un repo întreg (cod, dependințe, IaC, secrete)
trivy fs --scanners vuln,secret,misconfig,license ./

# Generează SBOM CycloneDX pentru satisfacția NIS2 / EO 14028
trivy image --format cyclonedx --output api-sbom.json api:v1.4.2

Politicile custom se adaugă cu --config-policy ./policies --policy-namespaces custom, unde policies/ conține fișiere Rego proprii. Am folosit acest pattern pentru a interzice image-uri fără runAsNonRoot: true, fără să depind de admission controller-e OPA Gatekeeper în cluster.

Trivy Operator pentru Kubernetes

Scanarea la build time oprește vulnerabilitățile cunoscute, dar CVE noi apar zilnic pentru imagini care erau curate ieri. Trivy Operator rezolvă acest gap: rulează ca un deployment în cluster, watch-uiește resurse Kubernetes (Pod, Deployment, DaemonSet, ConfigMap, Secret, RoleBinding) și emite rescanare periodică, implicit la 6 ore.

Instalare cu Helm:

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.scanJobTimeout=10m \
  --set trivyOperator.scanJobsConcurrentLimit=5

După câteva minute, cluster-ul are trei tipuri noi de resurse pe care le poți interoga cu kubectl:

# Vulnerabilități per workload, sortate după CRITICAL
kubectl get vulnerabilityreports -A \
  -o custom-columns=NS:.metadata.namespace,\
NAME:.metadata.name,\
CRIT:.report.summary.criticalCount,\
HIGH:.report.summary.highCount

# Audit configurare pod (privileged, hostNetwork, capabilities)
kubectl get configauditreports -A

# Analiză RBAC: role-uri cu permisiuni excesive
kubectl get rbacassessmentreports -A

Rezultatele sunt exportate nativ către Prometheus în formatul trivy_image_vulnerabilities{severity="CRITICAL"}, deci le poți vizualiza în Grafana și le poți lega la alerte Alertmanager. Pentru contextul mai larg de detectare runtime, complementează Trivy Operator cu Falco și eBPF pentru monitorizare runtime în containere. Trivy vede „ce este în imagine", Falco vede „ce face procesul acum".

Cum integrezi Trivy într-un pipeline CI/CD

Un gate CI/CD bun face trei lucruri: (1) scanează la fiecare push, (2) fails-fast pe CVE critice noi, (3) publică raportul pe PR pentru triage. Iată un exemplu complet pentru GitHub Actions cu aquasecurity/trivy-action:

name: container-security
on:
  pull_request:
    paths: ['Dockerfile', 'src/**']
  schedule:
    - cron: '0 4 * * *'   # rescanare nocturnă pentru CVE noi

permissions:
  contents: read
  security-events: write   # necesar pentru upload SARIF

jobs:
  scan:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v4

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

      - name: Trivy scan (blocking)
        uses: aquasecurity/[email protected]
        with:
          image-ref: api:${{ github.sha }}
          format: sarif
          output: trivy-results.sarif
          severity: 'HIGH,CRITICAL'
          ignore-unfixed: true
          exit-code: '1'
          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

Pentru GitLab CI, include template-ul oficial și adaugă politici custom:

include:
  - template: Security/Container-Scanning.gitlab-ci.yml

container_scanning:
  variables:
    CS_SEVERITY_THRESHOLD: HIGH
    CS_IGNORE_UNFIXED: "true"
    CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  rules:
    - if: $CI_MERGE_REQUEST_ID
    - if: $CI_COMMIT_BRANCH == "main"

Un audit pe care îl fac frecvent este să verific dacă gate-ul chiar oprește build-ul. Introdu intenționat o dependință vulnerabilă ([email protected] are un CVE critic) și confirmă că pipeline-ul eșuează. Dacă trece, ai un gate mort. E foarte comun cu --exit-code 0 lăsat din prima iterație, iar clientul jură că „e configurat".

Cum ignori vulnerabilitățile în Trivy fără să pierzi vizibilitatea

Nu toate CVE-urile pot fi patched imediat. Câteodată fix-ul upstream lipsește, alteori vulnerabilitatea nu este exploatabilă în contextul aplicației tale (ex: un CVE în cod pe care nu-l apelezi niciodată). Trivy oferă două mecanisme:

1. Fișier .trivyignore simplu (câte un CVE pe linie):

# .trivyignore
CVE-2024-45490   # libexpat, nu procesăm XML în această aplicație
CVE-2024-6119    # OpenSSL, versiunea vulnerabilă neatinsă la runtime

2. Fișier .trivyignore.yaml cu expirare, preferat, pentru că forțează revizuire periodică:

vulnerabilities:
  - id: CVE-2024-45490
    paths:
      - "usr/lib/x86_64-linux-gnu/libexpat.so.1.9.0"
    statement: "Nu procesăm XML extern; expirat pentru re-triage."
    expired_at: 2026-12-31

misconfigurations:
  - id: AVD-DS-0002
    paths:
      - "Dockerfile"
    statement: "USER root necesar pentru bind pe port 80 în init."
    expired_at: 2026-10-01

Recomandarea mea din audit-uri: nu accepta niciodată o excepție fără expired_at. Fișierele .trivyignore lăsate deschise se transformă în cimitire de datorie de securitate care ascund CVE-uri de mult exploatabile. Pentru un cadru de audit mai amplu al Linux-ului, consultă și ghidul complet auditd pentru audit al sistemului Linux.

Trivy vs. Grype: care este mai bun în 2026

Grype (dezvoltat de Anchore) este cel mai apropiat competitor open-source. Ambele sunt gratuite, ambele sunt binaruri Go, ambele scanează imagini OCI. Diferențele contează pentru alegere.

CaracteristicăTrivyGrype
Scanare imagini containerDaDa (30–40% mai rapid)
Scanare IaC (Terraform, K8s)DaNu
Detectare secreteDaNu
Detectare misconfigurări DockerfileDaNu
Generare SBOM (CycloneDX, SPDX)Da nativPrin Syft (separat)
Operator KubernetesTrivy Operator (oficial)Fără operator oficial
Surse CVENVD, GHSA, GitLab, Red Hat, Debian, Alpine, distro-specificNVD, GHSA, distro-specific
Cel mai bun pentruDevSecOps end-to-endCross-check de viteză

În practică, majoritatea echipelor mature aleg Trivy ca scanner principal (un tool, un output format, o comandă de învățat) și rulează ocazional Grype pe imaginile critice pentru „a doua opinie". Divergențele între cei doi scanneri sunt semnale: dacă doar unul raportează un CVE, verifică-l manual în NVD.

Atacul: cum ajunge o imagine „curată" să compromită producția

Ca pen tester, iată lanțul de atac tipic pe care îl reproduc când clientul spune „containerele noastre sunt scanate":

  1. Pasul 1, dev push: un developer face docker build cu un base image node:18-alpine, netaguit exact. Alpine primește un upgrade la musl cu CVE-2024-xxxx.
  2. Pasul 2, CI verde: scanarea Trivy rulează la build-time cu --severity CRITICAL, dar CVE-ul este HIGH. Pipeline-ul trece.
  3. Pasul 3, deploy: imaginea ajunge în cluster. Nu există Trivy Operator, deci nu se face rescanare.
  4. Pasul 4, escalare: două săptămâni mai târziu, CVE-ul devine CRITICAL după re-analiză. Nimeni nu observă pentru că imaginea nu se rebuild-uiește.
  5. Pasul 5, exploit: request malițios spre serviciu declanșează heap overflow în musl, RCE ca root în container. Fără AppArmor/SELinux enforcing, breakout în cluster.

Fiecare pas are un control de hardening corespunzător:

  • Pas 1, pinning imagini prin digest: folosește node@sha256:..., nu tag-uri mutable.
  • Pas 2, gate pe HIGH+CRITICAL: nu doar CRITICAL. Costul fals-pozitivelor merită.
  • Pas 3, Trivy Operator: rescanare cluster la 6 ore, alertă Prometheus pe trivy_image_vulnerabilities{severity="CRITICAL"} > 0.
  • Pas 4, rebuild nocturn: cron GitHub Actions care rebuild-uiește și redeploy-uiește imagini cu tag-uri floating.
  • Pas 5, defense-in-depth: seccomp profile runtime/default, readOnlyRootFilesystem: true, network policy restrictivă, plus firewall nftables la nivel de nod pentru izolare est-vest.

Verificarea integrității cu attestations și Cosign

Trivy 0.55+ verifică nativ semnături Sigstore și attestations SLSA pentru imagini semnate cu Cosign. Adaugă în pipeline-ul CI verificarea semnăturii înainte de scanare:

cosign verify \
  --certificate-identity-regexp "^https://github.com/myorg/" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  myregistry.io/api:v2.1.0

trivy image \
  --check-supply-chain \
  --severity CRITICAL,HIGH \
  --exit-code 1 \
  myregistry.io/api:v2.1.0

Această combinație oprește nu doar CVE-uri, ci și imagini care au fost tampered în tranzit sau publicate din pipeline-uri necunoscute. Este cerința minimă pentru compliance SLSA Level 2.

Întrebări frecvente

Este Trivy gratuit pentru uz comercial?

Da. Trivy este open source sub licența Apache 2.0 și poate fi utilizat gratuit inclusiv în producție comercială. Aqua Security oferă produse comerciale (Aqua Enterprise, Aqua Trivy Premium) cu suport SLA și baze de date extinse, dar CLI-ul și Trivy Operator rămân complet gratuite.

Cât de des își actualizează Trivy baza de date de vulnerabilități?

Baza de date oficială este reconstruită automat la 6 ore din surse NVD, GHSA, GitLab Advisory, Red Hat, Debian, Ubuntu, Alpine și Amazon Linux. Cache-ul local se refresh-uiește la prima rulare după expirare; poți forța actualizarea cu trivy image --download-db-only.

Poate Trivy să scaneze imagini fără să le pull-uiască local?

Da, cu flag-ul --image-src remote, Trivy citește manifestul și layer-ele direct din registru fără să pull-uiască imaginea complet în stocarea locală. Este util pentru CI runner-e cu disc mic și pentru scanarea imaginilor mari de multi-arch.

Care este diferența între trivy image și trivy fs?

trivy image scanează un artefact OCI (imagine Docker/OCI, arhivă tar), reconstruind layerele filesystem-ului. trivy fs scanează un director sau repo direct, útil pentru scanare pre-commit sau în pipeline-uri care nu au acces la un daemon container. Ambele pot combina scanere pentru vulnerabilități, secrete, IaC și licențe.

Cum reduc falsele pozitive raportate de Trivy?

Folosește --ignore-unfixed pentru a exclude CVE-urile fără patch upstream, --vex pentru a consuma fișiere VEX (Vulnerability Exploitability eXchange) care atestă non-exploatabilitatea, și .trivyignore.yaml pentru excepții motivate cu dată de expirare. Evită să scazi threshold-ul global, pentru că pierzi vizibilitatea peste toate imaginile.

Trivy scanează imagini Windows containere?

Suport limitat. Trivy detectează pachetele instalate în imagini Windows Server Core prin catalogul MSI, dar acoperirea CVE este mult mai slabă decât pentru distribuțiile Linux. Pentru workload-uri Windows critice, folosește tool-uri specializate (Defender for Containers, Snyk Container) în paralel.

Felix Lindqvist
Despre Autor Felix Lindqvist

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