Un bucket S3 pubblico, un security group con la porta 22 aperta a 0.0.0.0/0, un disco cifrato dimenticato: sono errori che nascono in un file Terraform, non in un attacco sofisticato. Chi scrive infrastruttura come codice li introduce senza accorgersene, li committa, e li scopre solo quando qualcuno li trova per primo. Checkov nasce per intercettarli prima del deploy, direttamente nell’editor o nella pipeline CI/CD. In questa guida installiamo Checkov, scansioniamo un progetto Terraform reale con errori intenzionali, correggiamo ogni segnalazione e integriamo lo scanner in GitHub Actions. Dodici passi, circa 40 minuti, e un progetto funzionante a fine lettura.

Il pubblico di questa guida sono sviluppatori backend, ingegneri platform e chiunque scriva o revisioni codice Terraform su base regolare. Non serve esperienza pregressa con scanner di sicurezza: bastano familiarità di base con la riga di comando e un editor di testo. Alla fine avrai un progetto Terraform corretto, un file di configurazione riutilizzabile, un check personalizzato scritto in Python e una pipeline GitHub Actions che blocca automaticamente le pull request rischiose.

Perché la sicurezza dell’Infrastructure as Code conta nel 2026

Terraform, CloudFormation e Kubernetes manifest hanno spostato la configurazione cloud dentro un repository Git. È un bene per versionamento e revisione, ma significa anche che un errore di battitura in un file .tf può aprire un bucket a chiunque su internet. A differenza di un bug applicativo, un errore di configurazione infrastrutturale spesso non genera un crash visibile: il sistema funziona normalmente, solo che è esposto. Per questo motivo lo shift-left security, cioè lo spostamento dei controlli di sicurezza il più a monte possibile nel ciclo di sviluppo, è diventato uno standard de facto nei team DevSecOps. L’OWASP Infrastructure as Code Security Cheat Sheet raccomanda proprio di trattare i template IaC come codice sorgente da sottoporre a linting, test e scansione statica prima del merge, non come artefatti da controllare dopo il deploy.

Checkov si inserisce esattamente in questo punto del flusso. Gira localmente sul laptop dello sviluppatore, dentro una pipeline CI/CD o come pre-commit hook, e restituisce un elenco di violazioni prima che il codice raggiunga l’ambiente di produzione. Non serve un account cloud attivo né credenziali AWS o Azure: la scansione è statica, legge il testo del file e lo confronta con un catalogo di regole.

Cos’è Checkov e chi lo mantiene

Checkov è uno scanner statico open source per Infrastructure as Code, sviluppato originariamente da Bridgecrew e oggi mantenuto sotto l’ombrello di Prisma Cloud, la divisione di sicurezza cloud di Palo Alto Networks. Il progetto è pubblico su GitHub, ha superato le 9.000 stelle e riceve rilasci frequenti: l’ultima release stabile disponibile a settembre 2026 è la 3.3.19. È distribuito con licenza Apache 2.0, quindi utilizzabile liberamente anche in contesti commerciali senza costi di licenza per lo scanner in sé.

Il catalogo di regole integrate supera i 1.000 check e copre framework diversi: Terraform, OpenTofu, CloudFormation, AWS SAM, Kubernetes, Helm, Kustomize, Dockerfile, Serverless Framework, Ansible, Bicep, template ARM di Azure e persino file di workflow CI/CD come GitHub Actions, GitLab CI, CircleCI, Bitbucket Pipelines e Argo Workflows. Ogni check ha un identificativo univoco (per esempio CKV_AWS_20 per un bucket S3 con ACL pubblica) e una categoria di rischio assegnata, così da poter dare priorità alle correzioni più urgenti senza dover leggere manualmente centinaia di righe di configurazione.

Oltre alla scansione IaC pura, il progetto include moduli per il rilevamento di segreti hardcoded, per la scansione di immagini container referenziate nei manifest e per l’analisi di pacchetti open source dichiarati nei file di dipendenza. In questa guida ci concentriamo sul caso d’uso principale, la scansione Terraform, perché è il punto di ingresso più comune per chi adotta Checkov per la prima volta e perché copre la maggioranza dei casi reali in cui un errore di configurazione cloud nasce da codice infrastrutturale scritto a mano.

Checkov, Trivy, Terrascan e KICS: come scegliere lo scanner giusto

Checkov non è l’unico scanner IaC disponibile, ed è giusto sapere dove si colloca prima di adottarlo. Trivy, di cui abbiamo parlato in un’altra guida dedicata a cloud e Kubernetes, ha assorbito nel tempo le funzionalità di tfsec, il vecchio scanner Terraform-only, e oggi copre in un solo binario container, dipendenze, segreti e IaC. È la scelta più comoda quando si vuole un unico tool per tutto lo stack. Checkov, al contrario, punta sulla profondità delle policy e sulla personalizzazione: se serve scrivere regole aziendali su misura o mappare i check su framework di compliance specifici, Checkov offre più leva. Terrascan e KICS restano alternative valide con un approccio simile basato su query, ma con community e frequenza di rilascio meno intense rispetto ai primi due.

ScannerFocus principaleFormati IaC copertiStato nel 2026
CheckovPolicy-as-code multi-frameworkTerraform, CloudFormation, K8s, Helm, Docker, Ansible, Bicep, ARMSviluppo attivo, versione 3.3.19
TrivyScanner unificato (container + IaC + secrets)Terraform, CloudFormation, K8s, Docker, immagini e dipendenzeHa assorbito tfsec, sviluppo attivo
TerrascanCompliance e policy Terraform-centricheTerraform, K8s, Helm, CloudFormationManutenzione più lenta
KICSScansione query-based multi-IaCTerraform, CloudFormation, Ansible, Docker, K8sProgetto Checkmarx, attivo

Se il team gestisce già la scansione container e dipendenze con Trivy o Grype, aggiungere Checkov per l’IaC non è ridondante: i due strumenti guardano cose diverse e in molte pipeline convivono senza sovrapporsi.

Come Checkov analizza il codice: parsing e grafo delle risorse

A differenza di un semplice grep su parole chiave, Checkov trasforma ogni file Terraform in una rappresentazione strutturata (Abstract Syntax Tree) e poi costruisce un grafo delle risorse, dove ogni nodo è una risorsa e ogni arco rappresenta una relazione tra due risorse, per esempio un security group collegato a un’istanza EC2. Questo approccio permette di eseguire due categorie di check ben distinte. I check con prefisso CKV_ valutano una singola risorsa in isolamento, come verificare che un bucket S3 abbia la cifratura attiva. I check con prefisso CKV2_ analizzano invece relazioni tra più risorse, per esempio se un bucket privo di blocco pubblico è comunque raggiungibile tramite una policy IAM troppo permissiva assegnata a un altro componente dello stack.

Questa distinzione conta nella pratica quotidiana: un check CKV2 può individuare un problema che nessuna singola riga di codice rivela da sola, ma che emerge solo guardando l’infrastruttura come sistema. È anche il motivo per cui scansionare un modulo isolato, senza il contesto del resto del progetto, a volte produce risultati diversi rispetto a scansionare l’intero repository. Quando un team lavora con moduli Terraform condivisi tra più progetti, vale la pena eseguire almeno una scansione periodica sull’intero ambiente aggregato, non solo sui singoli moduli presi separatamente.

Prerequisiti e versioni consigliate

Prima di iniziare, verifica di avere questi strumenti installati. Le versioni indicate sono quelle testate per questa guida a settembre 2026.

StrumentoVersione minimaRuolo nel progetto
Python3.9 – 3.13Runtime richiesto da Checkov
pip / pipxultima versioneInstallazione del pacchetto checkov
Checkov3.3.19Lo scanner IaC vero e proprio
Terraform CLI1.9 o superiorePer generare il plan JSON al Passo 7
DockerfacoltativoAlternativa a pip per eseguire Checkov senza installarlo
Gitqualsiasi versione recenteVersionamento del progetto di esempio

Non servono credenziali AWS, Azure o GCP: la scansione statica legge solo il testo dei file .tf, non chiama le API del cloud provider. Le credenziali diventano necessarie solo se in futuro vuoi attivare i controlli runtime di Prisma Cloud, che esulano da questa guida.

Passo 1: installare Checkov con pip o Docker

Il metodo più diretto è installare Checkov via pip, preferibilmente dentro un ambiente virtuale per non sporcare l’installazione Python di sistema.

python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install checkov

# Verifica versione
checkov --version

Se preferisci non installare nulla in locale, l’immagine Docker ufficiale funziona altrettanto bene, comoda anche per usarla direttamente in pipeline CI/CD senza gestire dipendenze Python.

docker pull bridgecrew/checkov

docker run --rm -v "$PWD:/tf" bridgecrew/checkov -d /tf

Da qui in avanti la guida usa i comandi pip, ma ogni comando checkov può essere sostituito con l’equivalente docker run mostrato sopra, aggiungendo semplicemente il volume corretto.

Passo 2: verificare l’installazione e i comandi base

Prima di scansionare un progetto reale, vale la pena conoscere i flag principali del comando checkov. Sono pochi ma coprono la maggior parte dei casi d’uso quotidiani.

# Scansiona un'intera directory
checkov -d ./terraform

# Scansiona un singolo file
checkov -f ./terraform/main.tf

# Filtra per un solo framework
checkov -d . --framework terraform

# Mostra l'elenco completo dei check disponibili
checkov --list

Il comando –list è utile la prima volta: restituisce centinaia di righe con ID, descrizione e risorsa target di ogni check, un buon modo per capire cosa Checkov è in grado di rilevare prima ancora di lanciare una scansione vera.

Passo 3: preparare un progetto Terraform di esempio con errori reali

Per rendere concreta la guida, costruiamo un piccolo progetto Terraform che crea un bucket S3 e un security group, entrambi con configurazioni deliberatamente insicure. È il tipo di codice che capita di scrivere in fretta durante un prototipo, e che troppo spesso finisce dritto in produzione senza revisione.

mkdir checkov-demo && cd checkov-demo
mkdir terraform && cd terraform

Crea un file main.tf con questo contenuto:

provider "aws" {
  region = "eu-west-1"
}

resource "aws_s3_bucket" "logs" {
  bucket = "acme-app-logs-demo"
}

resource "aws_s3_bucket_acl" "logs_acl" {
  bucket = aws_s3_bucket.logs.id
  acl    = "public-read"
}

resource "aws_security_group" "web" {
  name        = "web-sg"
  description = "Security group demo insicuro"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Questo file compila senza errori con terraform validate: sintatticamente è perfetto. Il problema non è la sintassi, è la sicurezza, ed è esattamente il tipo di difetto che un linter classico non intercetta ma che Checkov segnala nel giro di pochi secondi.

Passo 4: eseguire la prima scansione

Torna nella cartella principale del progetto e lancia Checkov puntando alla directory terraform.

cd ..
checkov -d ./terraform --compact

L’output elenca ogni check eseguito, distingue tra check superati (passed) e falliti (failed), e per ciascun fallimento indica file, numero di riga e una breve descrizione del problema. Su questo progetto di esempio, Checkov segnala tra gli altri il bucket con ACL pubblica, l’assenza di cifratura server-side sul bucket, il logging di accesso mancante e la porta 22 aperta al mondo intero.

Passo 5: leggere l’output, check ID e categorie di rischio

Un output tipico di Checkov su questo progetto assomiglia a questo estratto, semplificato per leggibilità:

Check: CKV_AWS_20: "S3 Bucket has an ACL defined which allows public READ access"
	FAILED for resource: aws_s3_bucket_acl.logs_acl
	File: /terraform/main.tf:9-11

Check: CKV_AWS_21: "Ensure S3 bucket has versioning enabled"
	FAILED for resource: aws_s3_bucket.logs
	File: /terraform/main.tf:5-7

Check: CKV2_AWS_6: "Ensure S3 bucket has public access block"
	FAILED for resource: aws_s3_bucket.logs
	File: /terraform/main.tf:5-7

Check: CKV_AWS_24: "Ensure no security groups allow ingress from 0.0.0.0:0 to port 22"
	FAILED for resource: aws_security_group.web
	File: /terraform/main.tf:14-27

Passed checks: 3, Failed checks: 7, Skipped checks: 0

Ogni ID segue una convenzione leggibile: il prefisso CKV_AWS indica un check specifico per AWS, CKV2_ indica un check che analizza le relazioni tra più risorse invece di una sola. Checkov non assegna un punteggio CVSS come per le CVE, ma raggruppa le violazioni per categoria di rischio (esposizione di rete, cifratura, logging, identità), un criterio più utile per decidere cosa correggere prima quando il tempo è limitato.

Categoria di rischioEsempio di checkPriorità tipica di intervento
Esposizione di reteSecurity group aperto a 0.0.0.0/0 su porte sensibiliImmediata
Dati non cifratiBucket S3 o volume EBS senza cifratura server-sideAlta
Accesso pubblicoACL public-read, bucket policy permissivaImmediata
Logging assenteNessun access log su bucket o load balancerMedia
IAM troppo permissivoPolicy con Action “*” e Resource “*”Alta

Passo 6: correggere le violazioni rilevate

Con l’elenco dei check falliti in mano, riscriviamo il file main.tf applicando le correzioni: ACL privata, blocco esplicito dell’accesso pubblico, cifratura server-side, versioning attivo e ingress SSH ristretto a un range interno invece che aperto al mondo.

resource "aws_s3_bucket" "logs" {
  bucket = "acme-app-logs-demo"
}

resource "aws_s3_bucket_acl" "logs_acl" {
  bucket = aws_s3_bucket.logs.id
  acl    = "private"
}

resource "aws_s3_bucket_versioning" "logs_versioning" {
  bucket = aws_s3_bucket.logs.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "logs_sse" {
  bucket = aws_s3_bucket.logs.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "aws:kms"
    }
  }
}

resource "aws_s3_bucket_public_access_block" "logs_block" {
  bucket                  = aws_s3_bucket.logs.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_security_group" "web" {
  name        = "web-sg"
  description = "Security group corretto"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/16"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Rilancia checkov -d ./terraform: i check falliti dovrebbero scendere a zero, o quasi. L’unico ingress ancora ampio è l’egress verso 0.0.0.0/0, comune e generalmente accettato per il traffico in uscita, ma anche quello può essere ristretto se il progetto lo richiede. Nota che nessuna delle correzioni applicate qui cambia il comportamento funzionale dell’infrastruttura: il bucket continua a ricevere log, il security group continua a permettere l’accesso SSH da dove serve davvero. Cambia solo la superficie di esposizione, che è esattamente l’obiettivo di questo tipo di scansione.

Passo 7: scansionare un Terraform plan invece del solo codice sorgente

Scansionare i file .tf grezzi ha un limite: non cattura i valori calcolati da variabili, moduli remoti o data source dinamici. Per una visione più fedele a ciò che verrà effettivamente applicato, Checkov può leggere l’output JSON di un Terraform plan.

cd terraform
terraform init
terraform plan -out=tf.plan
terraform show -json tf.plan > tf.json
checkov -f tf.json

Questo approccio è particolarmente utile in pipeline CI/CD dove il plan viene comunque generato come step di approvazione: aggiungere la scansione Checkov subito dopo costa un comando in più e blocca il merge se qualcosa di rischioso è stato introdotto, anche indirettamente tramite un modulo esterno.

Passo 8: personalizzare le regole con un file di configurazione

Non tutti i 1.000+ check integrati sono rilevanti per ogni progetto. Invece di passare decine di flag da riga di comando ogni volta, Checkov legge un file .checkov.yaml nella root del progetto con le impostazioni predefinite.

framework:
  - terraform
directory:
  - terraform
skip-check:
  - CKV_AWS_144   # replica cross-region non richiesta in dev
output: cli
compact: true
soft-fail: false
download-external-modules: true

Con questo file, basta lanciare checkov senza altri argomenti perché venga applicata la configurazione salvata. È il metodo consigliato per mantenere coerenza tra scansioni locali e quelle eseguite in pipeline, evitando che uno sviluppatore scansioni con impostazioni diverse da quelle usate in CI.

Passo 9: scrivere un check personalizzato in Python

Quando una policy aziendale non ha un check equivalente nel catalogo standard, Checkov permette di scriverne uno su misura. Ogni check custom estende una classe base e implementa la logica di validazione su una risorsa specifica.

from checkov.common.models.enums import CheckCategories, CheckResult
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck

class RequireOwnerTag(BaseResourceCheck):
    def __init__(self):
        name = "Ensure S3 buckets have an Owner tag"
        id = "CKV_CUSTOM_1"
        supported_resources = ["aws_s3_bucket"]
        categories = [CheckCategories.GENERAL_SECURITY]
        super().__init__(name=name, id=id, categories=categories,
                          supported_resources=supported_resources)

    def scan_resource_conf(self, conf):
        tags = conf.get("tags")
        if tags and "Owner" in tags[0]:
            return CheckResult.PASSED
        return CheckResult.FAILED

check = RequireOwnerTag()

Salva il file in una cartella dedicata, per esempio custom_checks/, e caricala con il flag –external-checks-dir.

checkov -d ./terraform --external-checks-dir ./custom_checks

Da questo momento in poi, ogni bucket S3 privo del tag Owner comparirà tra i check falliti insieme a quelli integrati, con lo stesso formato di output.

Passo 10: sopprimere i falsi positivi senza disabilitare l’intero check

A volte una risorsa viola un check per una ragione legittima e documentata: un bucket pubblico usato per servire asset statici di un sito web ne è l’esempio classico. Disabilitare il check a livello globale nasconderebbe il problema anche dove è reale. Meglio sopprimerlo puntualmente con un commento inline.

resource "aws_s3_bucket_acl" "static_site_acl" {
  #checkov:skip=CKV_AWS_20:Bucket pubblico per hosting sito statico, revisionato il 2026-09-10
  bucket = aws_s3_bucket.static_site.id
  acl    = "public-read"
}

Il commento resta nel codice sorgente, quindi è visibile in ogni code review futura e in ogni ricerca full-text sul repository: chi legge il file capisce subito perché quella deroga esiste, senza dover consultare un documento separato che rischia di finire dimenticato.

Passo 11: integrare Checkov in GitHub Actions

Una scansione locale aiuta lo sviluppatore, ma il vero valore arriva quando Checkov blocca automaticamente una pull request con violazioni non giustificate. GitHub mette a disposizione un’action ufficiale mantenuta da Bridgecrew.

name: checkov-iac-scan
on:
  pull_request:
    paths:
      - 'terraform/**'

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

      - name: Run Checkov
        uses: bridgecrewio/checkov-action@master
        with:
          directory: terraform
          framework: terraform
          soft_fail: false
          output_format: sarif
          output_file_path: reports/results.sarif

      - name: Upload SARIF to GitHub Code Scanning
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: reports/results.sarif

Con soft_fail impostato a false, la pipeline fallisce e blocca il merge se restano check critici non risolti o non soppressi esplicitamente. Se il team preferisce un approccio graduale durante l’adozione iniziale, soft_fail: true riporta le violazioni senza bloccare la build, utile nelle prime settimane per non paralizzare il flusso di lavoro mentre si sistemano i debiti pregressi.

Chi gestisce anche la supply chain delle dipendenze npm può abbinare questa pipeline a quanto descritto nella nostra guida su npm provenance e Sigstore, costruendo così un controllo end-to-end che copre sia il codice infrastrutturale sia le dipendenze applicative.

Chi lavora con GitLab invece di GitHub può ottenere lo stesso risultato richiamando direttamente l’immagine Docker ufficiale dentro un job della pipeline .gitlab-ci.yml, senza dipendere da un’action di terze parti.

checkov-scan:
  stage: test
  image:
    name: bridgecrew/checkov:latest
    entrypoint: [""]
  script:
    - checkov -d terraform --framework terraform -o cli -o junitxml --output-file-path console,reports
  artifacts:
    reports:
      junit: reports/results_junitxml.xml
    when: always

Il vantaggio di questo approccio è la portabilità: lo stesso comando checkov gira identico in locale, su GitHub Actions e su GitLab CI, riducendo il rischio che una scansione passi in un ambiente e fallisca in un altro per una differenza di configurazione tra le due pipeline.

Passo 12: generare report SARIF, JUnit e badge di conformità

Checkov supporta diversi formati di output oltre al testo semplice da terminale, utili per integrarsi con dashboard, strumenti di code scanning o report da allegare ad audit di conformità.

# Formato SARIF, per GitHub Code Scanning o strumenti SAST
checkov -d ./terraform -o sarif --output-file-path reports

# Formato JUnit XML, per dashboard CI classiche (Jenkins, GitLab)
checkov -d ./terraform -o junitxml --output-file-path reports

# Formato JSON, per elaborazione programmatica
checkov -d ./terraform -o json --output-file-path reports

# Più formati insieme in un solo comando
checkov -d ./terraform -o cli -o json --output-file-path console,reports

Il formato JSON è quello più comodo da elaborare con uno script personalizzato, per esempio per calcolare un punteggio di conformità nel tempo o per popolare una dashboard interna che tracci il numero di violazioni per team, un dato spesso più utile del semplice conteggio totale per capire dove concentrare la formazione.

Prestazioni su repository di grandi dimensioni

Su un monorepo con centinaia di moduli Terraform, una scansione completa può richiedere diversi minuti, soprattutto se include il download di moduli remoti a ogni esecuzione. Tre accorgimenti riducono il tempo di scansione senza perdere copertura. Primo: limita il framework analizzato con –framework quando il repository contiene anche manifest Kubernetes o Dockerfile che non sono cambiati in quella pull request, così Checkov non li rianalizza inutilmente. Secondo: usa –compact e disattiva l’output dettagliato in CI, dato che il parsing dell’output testuale completo ha un costo non trascurabile su repository con migliaia di risorse. Terzo: nelle pipeline che eseguono scansioni frequenti, valuta la cache dei moduli Terraform scaricati tra un’esecuzione e l’altra invece di riscaricarli ogni volta, un’ottimizzazione che spesso incide più della configurazione di Checkov stessa sul tempo totale della pipeline.

Su repository particolarmente grandi, alcuni team scelgono di eseguire la scansione completa solo sul branch principale a cadenza schedulata, per esempio una volta al giorno, mentre sulle pull request limitano Checkov ai soli file modificati rispetto al branch di destinazione. Questo equilibrio mantiene la pipeline reattiva senza rinunciare a una visione completa della postura di sicurezza, che resta comunque aggiornata quotidianamente.

Errori comuni da evitare con Checkov

  • Attivare soft-fail: false ovunque il primo giorno. Su un repository con anni di debito infrastrutturale, questo blocca ogni pull request esistente. Meglio partire in modalità permissiva, misurare il numero di violazioni, e stringere gradualmente.
  • Sopprimere check con skip-check globali invece che inline. Disattivare CKV_AWS_20 a livello di intero progetto nasconde anche le violazioni future legittime, non solo quella specifica già revisionata.
  • Scansionare solo i file .tf sorgente e mai il plan JSON. Alcune configurazioni pericolose emergono solo dai valori calcolati da variabili o moduli remoti, invisibili nel codice statico.
  • Dimenticare di aggiornare Checkov regolarmente. Nuovi check vengono aggiunti ad ogni release: una versione ferma da mesi perde copertura su servizi cloud più recenti.
  • Trattare ogni check fallito come bloccante allo stesso modo. Non distinguere tra una porta SSH aperta al mondo e un tag mancante porta i team a ignorare gli alert per stanchezza da notifiche.
  • Non documentare il motivo di una soppressione. Un #checkov:skip senza spiegazione è indistinguibile, mesi dopo, da una svista: chi rilegge il codice non sa se quella deroga è ancora valida o va rimossa.

Risoluzione dei problemi più comuni

Checkov non trova alcun file da scansionare. Verifica che il flag -d punti alla cartella corretta e che i file abbiano estensione .tf, .yaml o .json riconosciuta. Un percorso relativo sbagliato è la causa più comune.

La scansione fallisce con un errore di download dei moduli esterni. Aggiungi il flag –download-external-modules true oppure verifica la connessione di rete verso il registry dei moduli Terraform: senza accesso, Checkov non può analizzare le risorse dichiarate dentro un modulo remoto.

Troppi falsi positivi su un modulo di terze parti. Usa –skip-path per escludere l’intera cartella del modulo esterno dalla scansione, dato che spesso non è modificabile e le sue violazioni non sono sotto il controllo del team.

Il comando checkov non viene riconosciuto dopo l’installazione. Controlla che l’ambiente virtuale sia attivo con source .venv/bin/activate, oppure che la cartella degli script pip sia nel PATH di sistema.

La pipeline CI/CD impiega troppo tempo a completare la scansione. Limita il framework analizzato con –framework terraform invece di scansionare tutti i framework supportati, e usa –compact per ridurre l’output se non serve il dettaglio completo.

Un check personalizzato non viene caricato. Verifica che il file Python nella cartella custom_checks non abbia errori di sintassi e che la classe erediti correttamente da BaseResourceCheck. Un errore di import silenzioso fa sì che Checkov ignori il file senza generare un errore visibile.

Il report SARIF non viene accettato da GitHub Code Scanning. Assicurati di usare la versione più recente di checkov-action, dato che il formato SARIF generato da versioni datate può non essere conforme allo schema richiesto dall’upload-sarif action.

Checkov segnala una risorsa che non esiste più nel file. Probabilmente Checkov sta leggendo un plan JSON non aggiornato: rigenera il plan con terraform plan -out=tf.plan prima di ripetere la conversione in JSON.

Il container Docker non trova la cartella montata. Su Windows con Docker Desktop, il percorso passato a -v deve usare il formato compatibile con il file sharing configurato (per esempio //c/progetti/terraform invece di C:\progetti\terraform). Su WSL2 è preferibile lavorare direttamente dentro il filesystem Linux per evitare rallentamenti e problemi di permessi.

Un check custom scritto per Terraform non scatta su un file CloudFormation equivalente. I check personalizzati sono legati al framework dichiarato nella classe: se serve la stessa regola su più framework, occorre scrivere una classe separata per ciascuno, dato che la struttura interna del grafo delle risorse cambia da un framework all’altro.

Suggerimenti avanzati per un uso professionale

Una volta superata la fase di adozione iniziale, alcune pratiche rendono Checkov parte naturale del flusso di lavoro invece di un ostacolo. Attivarlo come pre-commit hook, tramite il framework pre-commit standard, intercetta le violazioni prima ancora del push, riducendo il numero di pull request respinte dalla pipeline. Mappare i check integrati sui framework di conformità richiesti dall’organizzazione, come CIS Benchmark, NIST o PCI DSS, aiuta a produrre report utili anche per gli audit, dato che Checkov etichetta molti check con il riferimento al benchmark di origine.

Vale anche la pena combinare Checkov con uno scanner di segreti dedicato: individuare una chiave AWS hardcoded in un file Terraform è un caso d’uso che Checkov copre solo in parte. Chi ha già una pipeline SBOM per le dipendenze applicative può integrare i due flussi, come descritto nella nostra guida su CycloneDX e SPDX, ottenendo una visione più ampia della postura di sicurezza dell’intero progetto, non solo dell’infrastruttura.

Infine, se il team lavora già con strumenti di audit per la postura cloud a runtime come quelli confrontati nella nostra analisi Prowler vs ScoutSuite, Checkov copre la fase precedente del ciclo: previene la configurazione errata prima del deploy, mentre Prowler e ScoutSuite verificano cosa è realmente attivo nell’account cloud dopo che le risorse sono state create. Usarli insieme chiude il cerchio tra prevenzione e rilevamento.

Misurare l’adozione di Checkov nel tempo

Introdurre uno scanner non basta: bisogna anche capire se sta funzionando. Un modo pratico è esportare il report JSON a ogni esecuzione della pipeline e salvarlo come artefatto, così da poter tracciare nel tempo tre numeri semplici: il totale dei check eseguiti, quelli falliti e quelli soppressi con skip-check documentato. Un aumento costante delle soppressioni senza una motivazione scritta è un segnale di allarme quanto un aumento dei check falliti: significa che il team sta imparando a bypassare lo strumento invece di correggere il codice.

Molti team stabiliscono una soglia di conformità minima per repository, per esempio il 95% dei check superati sul totale applicabile, e la usano come gate nella pipeline al posto di un blocco rigido su ogni singolo fallimento. Questo approccio lascia margine per eccezioni motivate senza rinunciare a un miglioramento misurabile nel tempo, ed è più facile da comunicare a un responsabile non tecnico rispetto a un elenco grezzo di check ID.

Il progetto completo: checklist finale

A fine guida, la struttura del progetto dimostrativo dovrebbe contenere questi elementi, pronti per essere riusati come punto di partenza su un progetto reale.

  • checkov-demo/terraform/main.tf, con le risorse S3 e security group corrette
  • checkov-demo/.checkov.yaml, con la configurazione predefinita del team
  • checkov-demo/custom_checks/require_owner_tag.py, con la policy aziendale personalizzata
  • checkov-demo/.github/workflows/checkov-iac-scan.yml, per la scansione automatica su ogni pull request
  • Zero check falliti critici alla scansione finale, con le eventuali deroghe documentate tramite commento inline

Chi cerca invece un punto di partenza più ampio sulla remediation delle vulnerabilità applicative, non infrastrutturali, troverà utile anche la nostra guida alla remediation OWASP Top 10:2025, che copre il lato codice applicativo dello stesso problema di fondo: prevenire prima di dover reagire.

Domande frequenti su Checkov

Cos’è esattamente Checkov e chi lo sviluppa?
È uno scanner statico open source per Infrastructure as Code, creato da Bridgecrew e mantenuto oggi sotto Prisma Cloud (Palo Alto Networks). Analizza file Terraform, CloudFormation, Kubernetes e altri formati alla ricerca di configurazioni insicure prima del deploy.

Checkov è gratuito?
Sì, lo scanner è distribuito con licenza Apache 2.0 e può essere usato senza costi, anche in progetti commerciali. Esistono funzionalità aggiuntive a pagamento legate alla piattaforma Prisma Cloud, ma non sono necessarie per l’uso descritto in questa guida.

Checkov sostituisce Trivy o tfsec?
Non del tutto. Trivy ha assorbito le funzionalità di tfsec e copre anche container e dipendenze in un solo strumento. Checkov si concentra sulla profondità delle policy IaC e sulla personalizzazione delle regole: molti team li usano insieme invece di sceglierne uno solo.

Come ignoro un check che non si applica al mio progetto?
Usa un commento inline nel formato checkov:skip=CHECK_ID seguito dalla motivazione, sopra la risorsa interessata. Evita di disattivare un check a livello globale, perché nasconderebbe anche violazioni future legittime.

Checkov scansiona anche Kubernetes e Docker, non solo Terraform?
Sì. Il framework supporta manifest Kubernetes, Helm chart, Dockerfile, template CloudFormation, Bicep, Ansible e file di workflow CI/CD, oltre a Terraform e OpenTofu.

Serve un account cloud attivo per usare Checkov?
No. La scansione è statica e legge solo il testo dei file di configurazione, senza contattare le API di AWS, Azure o GCP. Le credenziali servono solo per funzionalità aggiuntive di Prisma Cloud non trattate in questa guida.

Come integro Checkov in una pipeline CI/CD?
La via più semplice su GitHub è l’action ufficiale bridgecrewio/checkov-action, mostrata al Passo 11. Altri sistemi CI possono richiamare direttamente il comando checkov o l’immagine Docker bridgecrew/checkov.

Cosa fare se Checkov segnala troppi falsi positivi?
Distingui tra falsi positivi genuini, da sopprimere con un commento documentato, e violazioni reali che richiedono solo una priorità diversa. Un file .checkov.yaml condiviso dal team riduce le discrepanze tra scansioni locali e quelle in pipeline, la causa più comune di segnalazioni inattese.

Che differenza c’è tra Checkov open source e Prisma Cloud?
Checkov è il motore di scansione gratuito, installabile e usabile in autonomia come mostrato in questa guida. Prisma Cloud è la piattaforma commerciale di Palo Alto Networks che aggiunge dashboard centralizzate, controlli a runtime sull’account cloud e funzionalità enterprise, ma non è necessaria per usare Checkov nella pipeline di sviluppo quotidiana.