Una configurazione Kubernetes lasciata con i privilegi sbagliati, un bucket S3 pubblico per errore, un Dockerfile che gira come root: sono queste le crepe che aprono la strada agli incidenti più costosi del cloud, non gli zero-day esotici. Trivy, lo scanner open source di Aqua Security, è diventato uno degli strumenti più usati per intercettare questi problemi prima che arrivino in produzione. In questa guida installiamo la versione più recente, la usiamo per analizzare container, manifest Kubernetes e codice Terraform, e costruiamo un progetto completo che blocca automaticamente i deployment pericolosi. Il tutto in italiano, passo dopo passo, con comandi che puoi copiare e incollare da subito.

Perché Trivy è diventato lo standard per le misconfigurazioni cloud

Trivy nasce come scanner di vulnerabilità per immagini container, ma nel corso degli anni si è trasformato in uno strumento multiuso: analizza immagini Docker, filesystem, repository Git, cluster Kubernetes attivi e codice Infrastructure as Code (Terraform, CloudFormation, Helm, Kubernetes YAML, Dockerfile, Azure ARM e playbook Ansible). Il progetto, mantenuto su GitHub da Aqua Security, ha superato le 36.000 stelle e mantiene un ritmo di rilascio pressoché mensile durante tutto il 2026, con la versione 0.71.0 uscita a giugno (supporto al rilevamento delle vulnerabilità .NET e a CycloneDX 1.6) e la 0.74.0 pubblicata il 14 agosto. È distribuito con licenza Apache 2.0, quindi gratuito sia per uso personale che commerciale, un dettaglio che pesa parecchio per le PMI italiane che non possono permettersi le licenze delle suite enterprise.

Per capire quanto sia cresciuto lo scope del progetto, basta guardare quanti target diversi copre oggi un singolo binario. Fino a qualche anno fa uno sviluppatore doveva mettere insieme tre o quattro tool distinti: uno per le immagini container, uno per le dipendenze applicative, uno per l’IaC e uno per i segreti hardcoded. Trivy li ha fusi in un’unica interfaccia a riga di comando, con una sintassi coerente tra i vari sottocomandi. Questo non significa che sostituisca ogni altro strumento di sicurezza, ma riduce parecchio la superficie di apprendimento per i team piccoli.

C’è anche un motivo di attualità più concreto per imparare a usarlo bene: ad aprile 2026, con il rilascio della versione 0.70.0, Aqua Security ha dovuto ruotare le chiavi GPG usate per firmare i pacchetti Debian e RPM di Trivy, in seguito a un incidente di sicurezza sulla catena di distribuzione. Non è un dettaglio da ignorare: se installi Trivy da un repository con una chiave vecchia o non verificata, stai introducendo lo stesso tipo di rischio di supply chain che lo strumento dovrebbe aiutarti a scovare. In questa guida vedremo anche come verificare l’installazione correttamente, non solo come lanciare gli scan.

Il caso d’uso centrale di questo tutorial è la scansione delle configurazioni errate (misconfiguration) su tre livelli: le immagini container che finiscono in produzione, i manifest Kubernetes che definiscono come girano i tuoi carichi di lavoro, e il codice Terraform che provisiona l’infrastruttura cloud vera e propria. Sono gli stessi tre livelli su cui, secondo le linee guida di incident response pubblicate da AWS, bisogna intervenire più spesso dopo una violazione: bucket S3 con policy troppo permissive, ruoli IAM con trust policy allargate, ACL dimenticate aperte. Se riesci a bloccare questi errori prima del deploy, elimini la causa numero uno di molte fughe di dati che leggiamo ogni settimana nelle cronache di sicurezza.

Vale la pena ricordare che il modello di responsabilità condivisa nel cloud (lo stesso principio descritto nella documentazione ufficiale Microsoft sul shared responsibility model) mette la sicurezza della configurazione sempre in capo al cliente, mai al provider cloud. AWS, Azure e Google Cloud proteggono l’infrastruttura fisica e i servizi gestiti, ma un bucket lasciato pubblico o un ruolo IAM troppo largo restano responsabilità di chi scrive il codice Terraform o il manifest Kubernetes. È proprio questo il vuoto che uno strumento come Trivy va a colmare, spostando il controllo il più a sinistra possibile nel ciclo di sviluppo, prima ancora che la risorsa venga creata sul cloud reale.

Prerequisiti e versioni per seguire la guida

Prima di lanciare il primo comando, verifica di avere questo elenco di strumenti installati con le versioni indicate. Non serve avere tutto identico al millimetro, ma restare vicini a queste versioni evita differenze di output che possono confondere durante i primi test.

  • Sistema operativo: Linux (Ubuntu 22.04+ o Debian 12+), macOS 14+ oppure Windows 11 con WSL2
  • Trivy versione 0.74.0 o superiore (la guida usa i comandi validi anche sulla serie 0.7x)
  • Docker Engine 27.x o Podman 5.x per gli scan sulle immagini container
  • kubectl 1.31 configurato con accesso a un cluster (va bene anche Minikube o Kind in locale)
  • Terraform 1.9 o superiore, se vuoi seguire la parte di scansione IaC
  • Git 2.4x per clonare il repository di esempio
  • Un account GitHub, se vuoi integrare gli scan nella pipeline CI/CD con GitHub Actions
  • Almeno 2 GB di RAM liberi e una connessione internet per scaricare il database delle vulnerabilità

Un appunto pratico: Trivy scarica un database di vulnerabilità (il cosiddetto vulnerability DB) al primo avvio e lo aggiorna periodicamente. Il file può pesare diverse centinaia di megabyte, quindi la prima esecuzione sarà più lenta delle successive. Tienilo a mente se stai testando la guida da una rete con banda limitata.

Passo 1: installare Trivy e verificarne l’autenticità

Su Linux basato su Debian o Ubuntu, il metodo consigliato è aggiungere il repository ufficiale e installare il pacchetto tramite apt, così le firme GPG vengono verificate automaticamente dal gestore pacchetti (particolarmente importante dopo la rotazione delle chiavi di aprile 2026):

sudo apt-get install -y wget gnupg
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | \
  gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
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

Su macOS con Homebrew il comando è più semplice, ma vale lo stesso principio: usa sempre il canale ufficiale, mai un binario scaricato da fonti terze.

brew install aquasecurity/trivy/trivy
trivy --version

L’output atteso del comando trivy --version mostra qualcosa di simile a questo, con numero di versione e data di build del database delle vulnerabilità:

Version: 0.74.0
Vulnerability DB:
  Version: 2
  UpdatedAt: 2026-09-18 06:12:33.104 +0000 UTC
  NextUpdate: 2026-09-19 06:12:33.104 +0000 UTC

Se il numero di versione risulta inferiore a 0.70.0, aggiorna subito: le versioni precedenti a quella data non includono la rotazione delle chiavi di firma e alcuni controlli di misconfigurazione più recenti aggiunti nel corso dell’anno.

Passo 2: il primo scan su un’immagine container

Partiamo dal caso più comune: analizzare un’immagine Docker prima di pubblicarla su un registry. Usiamo un’immagine Nginx pubblica come esempio, ma il comando funziona identico su qualunque immagine tu abbia in locale o remota.

trivy image --severity HIGH,CRITICAL nginx:1.27

L’output elenca ogni pacchetto vulnerabile trovato nell’immagine, con identificativo CVE, severità, versione installata e versione corretta disponibile. Un estratto tipico:

nginx:1.27 (debian 12.7)
=========================
Total: 14 (HIGH: 11, CRITICAL: 3)

┌──────────────┬────────────────┬──────────┬──────────────┬───────────────┐
│   Library    │ Vulnerability  │ Severity │ Fixed Version │     Title     │
├──────────────┼────────────────┼──────────┼──────────────┼───────────────┤
│ libssl3      │ CVE-2026-31201 │ CRITICAL │ 3.0.15-1     │ heap overflow  │
│ zlib1g       │ CVE-2026-12894 │ HIGH     │ 1:1.3.dfsg-1 │ buffer overrun │
└──────────────┴────────────────┴──────────┴──────────────┴───────────────┘

Il flag --severity filtra il rumore: senza di esso, Trivy mostra anche le vulnerabilità di severità LOW e MEDIUM, che su un’immagine base come Debian possono facilmente superare le cento voci. Per un primo controllo rapido, concentrarsi su HIGH e CRITICAL è la scelta più sensata: quelle voci sono quelle su cui un team di sicurezza vorrà una risposta entro pochi giorni, non entro il prossimo trimestre.

Passo 3: capire severità, exit code e formati di output

Un dettaglio che passa spesso inosservato la prima volta: di default, Trivy termina sempre con exit code 0, anche se trova vulnerabilità critiche. Questo va bene per un’ispezione manuale, ma è un problema se vuoi che una pipeline CI/CD si fermi in presenza di problemi gravi. Chi arriva da altri linter è abituato al comportamento opposto e spesso perde tempo a capire perché la build “verde” nasconde in realtà dei problemi seri. Il flag --exit-code risolve la questione:

trivy image --severity CRITICAL --exit-code 1 --format json --output report.json nginx:1.27

Con questa combinazione, se Trivy trova almeno una vulnerabilità CRITICAL il processo esce con codice 1 (utile per far fallire uno step di build), e il report completo viene salvato in formato JSON in report.json invece di essere stampato solo a schermo. I formati di output supportati includono anche table (quello di default, leggibile a occhio), sarif (per l’integrazione con GitHub Code Scanning) e cyclonedx per generare un SBOM, che vedremo più avanti.

FormatoComandoUso tipico
table--format tableLettura manuale a terminale
json--format jsonElaborazione automatica, script custom
sarif--format sarifGitHub Code Scanning, GitLab SAST
cyclonedx--format cyclonedxGenerazione SBOM per audit e compliance
template--format templateReport HTML o formati personalizzati

Passo 4: scansionare codice sorgente, filesystem e dipendenze

Oltre alle immagini già costruite, Trivy analizza direttamente una cartella di codice sorgente per trovare dipendenze vulnerabili (package.json, requirements.txt, go.mod, pom.xml e molti altri manifest sono supportati nativamente). È utile da lanciare in locale prima ancora di aprire una pull request:

trivy fs --scanners vuln,secret,misconfig ./mio-progetto

Il flag --scanners permette di scegliere quali controlli attivare in un’unica passata: vuln per le dipendenze vulnerabili, secret per credenziali hardcoded, misconfig per errori di configurazione nei file IaC presenti nella cartella. Su un progetto Node.js di medie dimensioni, un’esecuzione completa richiede in genere tra i 20 e i 40 secondi, molto meno rispetto a strumenti SAST più pesanti.

Passo 5: rilevare segreti prima che finiscano su Git

Le chiavi API dimenticate in un file di configurazione sono una delle cause più frequenti di incidenti legati alla supply chain: basta una ricerca automatizzata su repository pubblici per trovarle. Trivy include un motore di secret scanning che riconosce decine di pattern comuni (chiavi AWS, token GitHub, chiavi private RSA, credenziali Slack e molti altri):

trivy fs --scanners secret --severity CRITICAL,HIGH .

Se il team lavora con chiavi custom che non rientrano nei pattern predefiniti, è possibile aggiungere regole personalizzate in un file trivy-secret.yaml e richiamarlo con --secret-config trivy-secret.yaml. Vale la pena investire dieci minuti su questo file una volta sola: da lì in avanti, ogni scan futuro erediterà automaticamente le regole aggiuntive.

Passo 6: scansionare Terraform, Dockerfile e manifest Kubernetes (IaC)

Qui arriviamo al cuore della guida. Trivy include nove scanner IaC integrati che coprono Terraform, CloudFormation, manifest Kubernetes, Dockerfile, chart Helm, template Azure ARM, playbook Ansible e persino l’output dei piani Terraform. Il comando è lo stesso identico, indipendentemente dal formato: Trivy riconosce automaticamente il tipo di file e applica le regole corrette.

trivy config ./infrastruttura/

Immagina di avere questo blocco Terraform per un bucket S3, un errore comune che si ripete da anni nelle configurazioni cloud:

resource "aws_s3_bucket" "dati_clienti" {
  bucket = "azienda-dati-clienti"
}

resource "aws_s3_bucket_acl" "dati_clienti_acl" {
  bucket = aws_s3_bucket.dati_clienti.id
  acl    = "public-read"
}

Lanciando trivy config su questo file, lo scanner segnala immediatamente il bucket con ACL pubblica in lettura, l’assenza di crittografia lato server e la mancanza di versioning, con tanto di identificativo della regola violata (nel formato AVD-AWS-XXXX) e un link alla documentazione ufficiale di Trivy sul misconfiguration scanning che spiega come correggerlo. È esattamente il tipo di errore che, se sfuggito in produzione, finisce nei report di incident response come causa principale di esposizione dati.

Lo stesso comando funziona in modo identico su un manifest Helm o su un file CloudFormation: non serve imparare una sintassi diversa per ogni formato. Questo è probabilmente il vantaggio pratico più sottovalutato di Trivy rispetto a strumenti nati per un solo ecosistema (ad esempio un linter Terraform puro): un team che usa sia Terraform per l’infrastruttura AWS sia manifest Kubernetes per i workload applicativi può centralizzare i controlli di sicurezza in un solo strumento, con una sola pipeline di CI/CD da mantenere.

Passo 7: generare un SBOM con formato CycloneDX

Con l’aggiornamento del supporto a CycloneDX 1.6 arrivato nella versione 0.71.0 di giugno 2026, generare un Software Bill of Materials con Trivy è diventato un’operazione a un comando. Il SBOM è oggi richiesto sempre più spesso nei contratti B2B e negli audit di sicurezza, perché documenta ogni componente software presente in un’immagine o in un progetto:

trivy image --format cyclonedx --output sbom.json nginx:1.27

Il file generato può essere condiviso con clienti o revisori senza dover esporre il codice sorgente, e può a sua volta essere ripassato a Trivy in un secondo momento per verificare se nuove vulnerabilità sono emerse su componenti già catalogati (comando trivy sbom sbom.json).

Passo 8: costruire il progetto completo, un’app Flask vulnerabile

Mettiamo insieme tutto quello visto finora in un mini-progetto funzionante. Creiamo una struttura di cartelle con un’app Flask, un Dockerfile volutamente non ottimale e un manifest Kubernetes, poi la scansioniamo end-to-end.

mkdir progetto-trivy-demo && cd progetto-trivy-demo
mkdir k8s

cat > requirements.txt << 'EOF'
flask==2.2.2
requests==2.28.1
EOF

cat > Dockerfile << 'EOF'
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
EOF

cat > k8s/deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: demo
        image: demo-app:latest
        securityContext:
          privileged: true
EOF

Ora costruiamo l'immagine e lanciamo la scansione completa su tutti e tre i livelli: dipendenze, Dockerfile e manifest Kubernetes.

docker build -t demo-app:latest .
trivy image --severity HIGH,CRITICAL demo-app:latest
trivy config Dockerfile
trivy config k8s/deployment.yaml

Il risultato atteso su questo progetto: Trivy segnala Flask 2.2.2 come vulnerabile (versione con CVE note, va aggiornata almeno alla serie 3.0), il Dockerfile come privo di un utente non privilegiato (esegue tutto come root di default), e il manifest Kubernetes per l'uso di privileged: true, una delle configurazioni più pericolose in assoluto perché dà al container accesso quasi completo all'host. Sono tre categorie di errore completamente diverse, trovate con tre comandi che condividono lo stesso strumento e la stessa sintassi.

Passo 9: bloccare la pipeline CI/CD con GitHub Actions

Trovare gli errori in locale è un buon inizio, ma il vero guadagno arriva quando la pipeline blocca automaticamente un merge che introduce un problema critico. Ecco un workflow GitHub Actions minimo che integra Trivy e carica i risultati direttamente nella scheda Security del repository tramite SARIF:

name: trivy-scan
on: [pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Trivy vulnerability scan
        uses: aquasecurity/[email protected]
        with:
          scan-type: 'fs'
          scan-ref: '.'
          format: 'sarif'
          output: 'trivy-results.sarif'
          severity: 'CRITICAL,HIGH'
          exit-code: '1'
      - name: Upload risultati a GitHub Security
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: 'trivy-results.sarif'

Il parametro exit-code: '1' è quello che fa davvero la differenza: se una pull request introduce una vulnerabilità CRITICAL o HIGH, il check fallisce e (se configurato come required check su GitHub) il merge viene bloccato finché il problema non viene risolto o esplicitamente accettato via .trivyignore.

Passo 10: scansione continua del cluster Kubernetes con Trivy Operator

Scansionare i manifest prima del deploy è fondamentale, ma un cluster vivo cambia continuamente: nuove immagini vengono deployate, i pod vengono ricreati, le configurazioni driftano rispetto a quanto previsto in origine. Trivy Operator gira dentro al cluster e mantiene aggiornati i report di sicurezza in automatico, senza bisogno di rilanciare comandi manuali.

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 \
  --version 0.24.1

Una volta installato, l'operatore crea automaticamente delle risorse custom (VulnerabilityReport, ConfigAuditReport, RbacAssessmentReport) per ogni workload nel cluster. Per vedere lo stato generale in un colpo d'occhio:

kubectl get vulnerabilityreports --all-namespaces
kubectl get configauditreports --all-namespaces

Il ConfigAuditReport è particolarmente utile perché segnala anche configurazioni RBAC troppo permissive, come ServiceAccount con permessi cluster-admin assegnati senza un motivo evidente, un errore che negli ultimi report di incident response compare regolarmente tra le cause di escalation dei privilegi dopo una compromissione iniziale. Per un ripasso sui principi di base della sicurezza dei cluster, la documentazione ufficiale di Kubernetes sulla sicurezza resta il punto di partenza più affidabile prima di intervenire manualmente su RBAC e NetworkPolicy.

Passo 11: gestire i falsi positivi con .trivyignore e VEX

Non tutte le vulnerabilità segnalate sono realmente sfruttabili nel tuo contesto specifico: magari il codice vulnerabile in una libreria non viene mai chiamato dalla tua applicazione. Ignorare in silenzio è pericoloso, ma documentare la decisione è una pratica accettata. Il file .trivyignore nella root del progetto serve proprio a questo:

# .trivyignore
# CVE-2026-12894: funzione vulnerabile non raggiungibile dal nostro codice, verificato il 2026-09-10
CVE-2026-12894

# Esclusione con scadenza: da rivedere entro fine anno
CVE-2026-31502 exp:2026-12-31

Per un approccio più strutturato e verificabile, Trivy supporta anche il formato VEX (Vulnerability Exploitability eXchange), pensato per documentare in modo formale perché una vulnerabilità non è sfruttabile in un determinato prodotto, così che l'informazione possa essere condivisa con clienti e auditor senza dover riscrivere la giustificazione ogni volta.

Passo 12: velocizzare gli scan con cache e modalità client/server

Su una pipeline CI/CD con molte build al giorno, scaricare il database delle vulnerabilità ogni volta è uno spreco di tempo e banda. Trivy supporta una modalità client/server dove un'istanza centrale mantiene il database aggiornato e i client si limitano a interrogarla:

# Sul server centrale
trivy server --listen 0.0.0.0:8080 &

# Su ogni runner CI/CD
trivy image --server http://trivy-server.interno:8080 demo-app:latest

In alternativa, per pipeline più semplici, basta montare una cache persistente tra le esecuzioni con --cache-dir, così il database viene scaricato una volta sola e riutilizzato: su una pipeline con decine di build al giorno, questa singola modifica può tagliare diversi minuti dal tempo totale di esecuzione.

5 errori comuni da evitare con Trivy

  • Ignorare l'exit code di default. Senza --exit-code 1, uno scan che trova vulnerabilità CRITICAL termina comunque con successo agli occhi della pipeline. È l'errore di configurazione più comune tra chi integra Trivy per la prima volta in CI/CD.
  • Scansionare tutto senza filtrare per severità. Un report con centinaia di voci LOW e MEDIUM viene ignorato dal team dopo la seconda occhiata. Filtra su HIGH e CRITICAL per il gate automatico, tieni il resto per revisioni periodiche.
  • Non aggiornare il database delle vulnerabilità in ambienti air-gapped. Se il runner CI/CD non ha accesso a internet, Trivy userà un database vecchio senza avvisare in modo evidente. Serve un mirror interno aggiornato manualmente.
  • Usare .trivyignore come cestino permanente. Ogni esclusione senza data di scadenza tende a restare lì per sempre, anche quando la vulnerabilità diventa realmente sfruttabile. Aggiungi sempre una scadenza o una nota di revisione.
  • Scansionare solo le immagini e dimenticare l'IaC. Un'immagine pulita distribuita su un'infrastruttura con bucket pubblici o RBAC troppo permissivo non protegge da nulla: i tre livelli (immagine, cluster, infrastruttura) vanno coperti insieme.

Esempi di output e come leggerli correttamente

Un dubbio frequente tra chi inizia con Trivy riguarda la lettura dei livelli di severità: non tutti i CVE con score CVSS alto meritano la stessa urgenza. La tabella seguente riassume come impostare le soglie in base al contesto operativo più comune nei team italiani di piccole e medie dimensioni.

SeveritàQuando bloccare il deployTempo di risposta consigliato
CRITICALSempre, gate automatico obbligatorioEntro 24-48 ore
HIGHSì, salvo eccezione documentata in .trivyignoreEntro 7 giorni
MEDIUMNo, revisione in sprint successivoEntro 30 giorni
LOWNo, monitoraggio passivoRevisione trimestrale

Un altro output da imparare a leggere è il report di misconfigurazione IaC, che per ogni problema mostra tre elementi chiave: l'ID della regola (utile per cercarla nella documentazione ufficiale di Trivy), la riga esatta del file dove si trova l'errore, e un suggerimento di correzione diretto, spesso sufficiente a risolvere il problema senza dover consultare altre fonti.

Risoluzione dei problemi più comuni

  • "unable to open JVM class file" durante lo scan di un'immagine Java. Capita con immagini che usano JAR compressi in modo non standard. Aggiorna Trivy all'ultima versione: il parser Java viene rivisto quasi a ogni rilascio.
  • Il comando resta bloccato su "Downloading DB...". Verifica la connessione verso ghcr.io, dove è ospitato il database. Se sei dietro un proxy aziendale, imposta le variabili HTTP_PROXY e HTTPS_PROXY prima di lanciare il comando.
  • "context deadline exceeded" su cluster Kubernetes grandi. Aumenta il timeout di default con il flag --timeout 15m: su cluster con centinaia di pod, i 5 minuti di default non bastano.
  • Falsi positivi su librerie di sistema in immagini Alpine. Alpine usa musl invece di glibc e alcuni database di vulnerabilità non lo gestiscono in modo coerente. Verifica manualmente prima di escludere in blocco.
  • Il file .trivyignore non viene applicato. Controlla che il file si trovi nella directory da cui lanci il comando, non nella root del repository se stai scansionando una sottocartella.
  • Permission denied durante lo scan del filesystem locale. Alcuni file di configurazione richiedono permessi di lettura elevati. Su Linux, verifica i permessi con ls -la prima di lanciare lo scan con sudo, che può nascondere problemi di permessi reali in produzione.
  • Il report SARIF non compare nella scheda Security di GitHub. Verifica che il repository abbia GitHub Advanced Security attivo (gratuito sui repository pubblici) e che il job abbia i permessi security-events: write dichiarati nel workflow.
  • Risultati diversi tra due macchine con la stessa versione di Trivy. Quasi sempre è una questione di database delle vulnerabilità non allineato. Forza l'aggiornamento con trivy image --download-db-only su entrambe le macchine prima di confrontare.

Consigli avanzati per un uso in produzione

Una volta superata la fase di prova, ci sono alcune scelte architetturali che fanno la differenza su larga scala. La prima è separare gli scan di sviluppo (rapidi, con soglie permissive, pensati per il feedback immediato al developer) dagli scan di rilascio (completi, con soglie rigide, pensati per bloccare un deploy in produzione). Usare due configurazioni distinte, magari con due file trivy.yaml diversi richiamati con --config, evita il problema classico di dover scegliere tra pipeline troppo rumorose o troppo permissive.

La seconda raccomandazione riguarda l'integrazione con il resto dello stack di sicurezza: i report JSON di Trivy si prestano bene a essere inviati verso un SIEM (Wazuh, ad esempio, li ingerisce senza problemi tramite un semplice script di parsing) per correlare le vulnerabilità trovate nei container con gli eventi di rete osservati in produzione. Questo tipo di correlazione è quello che permette di capire rapidamente se una vulnerabilità nota viene effettivamente sfruttata contro l'infrastruttura reale, invece di restare una voce statica in un report.

Infine, per i team che gestiscono decine di repository, vale la pena centralizzare le policy di misconfigurazione custom (regole Rego scritte con Open Policy Agent, che Trivy supporta nativamente) in un repository condiviso, invece di duplicarle in ogni progetto. Un aggiornamento della policy si propaga così a tutta l'organizzazione con una singola modifica, riducendo il rischio che alcuni team restino indietro con regole obsolete.

Chi lavora su più cloud provider contemporaneamente (una situazione sempre più comune tra le aziende italiane di medie dimensioni che affiancano AWS per i carichi di lavoro principali e Azure per i servizi Microsoft 365 integrati) troverà utile sapere che i controlli IaC di Trivy non fanno distinzioni: le stesse regole di base su crittografia a riposo, logging attivo e accesso di rete ristretto si applicano sia ai template CloudFormation sia agli ARM template di Azure. Questo riduce il carico cognitivo per i team infrastrutturali che devono già barcamenarsi tra sintassi e servizi diversi da un provider all'altro.

Checklist prima di andare in produzione

Prima di considerare completata l'integrazione di Trivy nel proprio flusso di lavoro, vale la pena passare in rassegna questa checklist. È il riepilogo dei punti che, nella pratica, vengono dimenticati più spesso durante il primo rollout.

  • Il gate CI/CD blocca le vulnerabilità CRITICAL con --exit-code 1, non solo le stampa a schermo
  • Il file .trivyignore ha una data di revisione o di scadenza per ogni voce inserita
  • Gli scan IaC coprono sia Terraform sia i manifest Kubernetes, non solo uno dei due
  • Il database delle vulnerabilità viene aggiornato almeno una volta al giorno, anche nei runner self-hosted
  • Trivy Operator è installato sul cluster di produzione, non solo testato in locale
  • Il SBOM generato viene archiviato insieme a ogni release, non solo generato on demand
  • Le chiavi di firma del pacchetto Trivy installato sono aggiornate dopo la rotazione di aprile 2026
  • Il team ha una procedura scritta per gestire un avviso CRITICAL trovato fuori orario lavorativo

Come la scansione delle misconfigurazioni si collega alla OWASP Top 10

La categoria "Security Misconfiguration" compare stabilmente tra le voci principali della OWASP Top 10 da diverse edizioni consecutive, e non è un caso: gli errori di configurazione restano una delle cause più ricorrenti di violazioni sia lato applicativo che lato infrastruttura cloud. Quello che Trivy aggiunge rispetto a un semplice checklist manuale è la possibilità di trasformare quella categoria da un controllo occasionale, fatto magari una volta al trimestre durante un audit, a un controllo continuo integrato in ogni pull request.

Questo approccio è coerente anche con la direzione che sta prendendo la normativa europea sulla sicurezza del software: il Cyber Resilience Act, entrato in una fase di applicazione più stringente nel corso del 2026, chiede ai produttori di software di dimostrare tracciabilità sui componenti utilizzati (da qui l'importanza crescente del SBOM visto al Passo 7) e di gestire le vulnerabilità note in modo documentato lungo tutto il ciclo di vita del prodotto. Un flusso di lavoro che genera automaticamente SBOM, blocca le CRITICAL in pipeline e documenta le eccezioni con .trivyignore o VEX copre gran parte di questi requisiti senza dover costruire un processo separato solo per la conformità.

Trivy contro le alternative: quando ha senso usarlo

Trivy non è l'unico scanner sul mercato, e non è pensato per sostituire strumenti di monitoraggio runtime o piattaforme CSPM (Cloud Security Posture Management) complete che si occupano di configurazioni cloud a livello di intero account. Il suo punto di forza resta la combinazione di velocità, copertura multi-target (immagini, filesystem, IaC, cluster) e il fatto di essere completamente gratuito, che lo rende la scelta più naturale per chi vuole introdurre controlli di sicurezza automatizzati senza dover giustificare un budget aggiuntivo al management. Per organizzazioni più grandi con esigenze di compliance formale su più account cloud contemporaneamente, strumenti CSPM dedicati restano complementari, non sostitutivi, a quanto costruito in questa guida.

La tabella seguente riassume dove Trivy si posiziona rispetto a categorie di strumenti adiacenti, utile per capire cosa aspettarsi e cosa invece richiede uno strumento diverso.

Categoria di rischioTrivy la copre?Strumento complementare consigliato
Vulnerabilità in immagini containerSì, nativamente
Misconfigurazioni IaC (Terraform, K8s, Helm)Sì, nativamente
Segreti hardcoded nel codiceSì, nativamente
Configurazione errata a livello di account cloud interoParzialePiattaforma CSPM dedicata
Scansione di rete e host non containerizzatiNoNessus o OpenVAS
Rilevamento minacce runtime in tempo realeNoEDR/XDR o SIEM come Wazuh

Domande frequenti su Trivy e la scansione delle misconfigurazioni cloud

Trivy è davvero gratuito anche per uso commerciale?
Sì. Trivy è distribuito con licenza Apache 2.0 e può essere usato senza restrizioni sia in progetti personali che in ambienti aziendali. Aqua Security vende separatamente una piattaforma commerciale più ampia, ma lo scanner Trivy in sé resta gratuito.

Serve un account Aqua Security per usare Trivy?
No, Trivy funziona in modalità completamente standalone e non richiede alcuna registrazione o account per essere installato e utilizzato.

Trivy sostituisce completamente un vulnerability scanner di rete come Nessus o OpenVAS?
No. Trivy si concentra su immagini container, codice, dipendenze e configurazioni IaC/Kubernetes. Non fa scanning di rete o di infrastrutture non containerizzate: per quello restano necessari strumenti dedicati come Nessus o OpenVAS.

Con che frequenza va aggiornato il database delle vulnerabilità?
Il database viene aggiornato quotidianamente dagli sviluppatori. Per un uso in produzione con pipeline continue, è consigliabile forzare un controllo di aggiornamento almeno una volta al giorno, o affidarsi alla modalità client/server con un database centralizzato.

Trivy funziona anche su Windows senza WSL2?
Trivy ha un binario nativo anche per Windows, ma la maggior parte dei tutorial e delle integrazioni CI/CD assume un ambiente Linux o WSL2, che resta la configurazione più testata e documentata.

Cosa succede se ignoro un avviso di misconfigurazione IaC?
Nulla di automatico: Trivy segnala il problema ma non blocca l'apply di Terraform o il deploy Kubernetes da solo. Il blocco effettivo va implementato tramite l'exit code nella pipeline CI/CD, come mostrato nel Passo 9 di questa guida.

Quanto tempo richiede l'integrazione completa descritta in questa guida?
Per un progetto singolo con pipeline GitHub Actions già esistente, l'integrazione base (scan immagine più scan IaC con gate CRITICAL) richiede in genere tra i 45 e i 60 minuti, incluso il primo download del database delle vulnerabilità.

Trivy Operator rallenta le prestazioni del cluster Kubernetes?
L'impatto è generalmente contenuto perché gli scan vengono eseguiti come job separati e non intercettano il traffico applicativo in tempo reale. Su cluster con centinaia di workload è comunque consigliabile monitorare il consumo di CPU dei pod dell'operatore nelle prime settimane.

Conviene usare Trivy anche in un team di una sola persona o su un progetto personale?
Sì. Proprio perché è gratuito e non richiede infrastruttura dedicata, anche un progetto personale con un singolo Dockerfile trae beneficio da un controllo automatico prima del push su un registry pubblico. Il comando trivy image visto al Passo 2 richiede meno di un minuto e può diventare parte dell'abitudine quotidiana anche senza una pipeline CI/CD strutturata.