Escrever infraestrutura como código resolve o problema de reprodutibilidade, mas cria um novo risco: erros de configuração (misconfigurations) agora são versionados, replicados e revisados com a mesma pressa de qualquer outro código. Um bucket S3 público, um security group aberto para 0.0.0.0/0 ou um container rodando como root passam despercebidos em um terraform plan, porque o plan mostra o que vai mudar, não se aquilo é seguro.
É esse o problema que o Checkov resolve: análise estática de segurança (SAST) para arquivos de IaC, rodando antes do apply, direto no seu terminal, editor ou pipeline de CI/CD.
Este artigo cobre tudo para sair do zero: o que é, para quem é, como instalar, como usar no dia a dia e como integrar em um pipeline real.
O que é o Checkov
O Checkov é uma ferramenta open source de policy-as-code criada pela Bridgecrew (adquirida pela Palo Alto Networks) que analisa arquivos de infraestrutura como código em busca de erros de configuração de segurança, conformidade e boas práticas sem precisar aplicar nada na nuvem.
Ele funciona construindo um grafo de recursos a partir do seu código (Terraform, CloudFormation, Kubernetes, etc.), entendendo as relações entre eles, e comparando cada recurso contra centenas de checks pré-definidos como "bucket S3 não deve permitir acesso público" ou "security group não deve expor a porta 22 para a internet".
Principais características:
- Mais de 1.000 checks embutidos, cobrindo AWS, Azure, GCP e boas práticas gerais
- Suporte a múltiplas linguagens de IaC: Terraform, CloudFormation, Kubernetes, Helm, Dockerfile, Serverless Framework, ARM templates, Bicep e mais
- Checks escritos em Python ou YAML - customizáveis e extensíveis
- Análise baseada em grafo (entende variáveis, módulos e referências entre recursos, não só regex)
- Gratuito e open source (com uma camada paga opcional via Prisma Cloud para políticas centralizadas)
Para quem é o Checkov
| Perfil | Como usa o Checkov |
|---|---|
| Devs que escrevem Terraform/Helm | Roda local antes do commit, corrige o erro antes do PR |
| Times de DevOps/Platform | Integra no pipeline de CI/CD como gate obrigatório |
| Security Engineers / AppSec | Define políticas customizadas e audita compliance (CIS, PCI-DSS, SOC2) |
| SRE | Garante que ambientes de produção seguem baseline de segurança antes do deploy |
| Estudantes de Cloud/DevSecOps | Aprende boas práticas de segurança na prática, com feedback imediato |
Se você já usa terraform validate ou terraform plan no seu fluxo, o Checkov entra como uma etapa adicional, ele não substitui essas ferramentas, complementa: elas garantem que o código é sintaticamente correto, o Checkov garante que ele é seguro.
Pré-requisitos
- Python 3.8+ instalado
-
pipdisponível - Um projeto de IaC para testar (vamos usar Terraform no exemplo)
Verifique sua versão do Python:
python3 --version
1. Instalação
O Checkov pode ser instalado de várias formas. As mais comuns:
# Via pip (recomendado)
pip install checkov
# Via pipx (isola em ambiente virtual próprio)
pipx install checkov
# Via Homebrew (macOS/Linux)
brew install checkov
# Via Docker (sem instalar nada localmente)
docker pull bridgecrew/checkov
Confirme a instalação:
checkov --version
No Debian/Ubuntu, se
pip install checkovreclamar de ambiente gerenciado externamente (PEP 668), usepipx install checkovou crie um virtualenv (python3 -m venv .venv && source .venv/bin/activate).
2. Primeiro scan: encontrando problemas reais
Vamos criar um exemplo propositalmente inseguro para ver o Checkov em ação.
mkdir -p ~/checkov-demo && cd ~/checkov-demo
Crie o arquivo main.tf:
resource "aws_s3_bucket" "data" {
bucket = "minha-empresa-dados-2026"
}
resource "aws_security_group" "web" {
name = "web-sg"
description = "Security group da aplicacao web"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_db_instance" "main" {
identifier = "app-db"
engine = "mysql"
instance_class = "db.t3.micro"
allocated_storage = 20
username = "admin"
password = "SenhaSuperSecreta123"
publicly_accessible = true
skip_final_snapshot = true
}
Rode o scan apontando para o diretório:
checkov -d .
O Checkov vai listar dezenas de checks, com resultado PASSED ou FAILED para cada recurso. Entre os FAILED esperados neste exemplo:
-
CKV_AWS_24 — Security group permite SSH (porta 22) aberto para
0.0.0.0/0 - CKV_AWS_260 — Security group permite HTTP aberto para o mundo sem necessidade
- CKV_AWS_16 — Instância RDS sem criptografia habilitada
- CKV_AWS_161 — Instância RDS não força autenticação via IAM
- CKV_AWS_129 — RDS sem logging de auditoria habilitado
-
CKV_SECRET_2 — Senha em texto plano detectada no código (
password = "SenhaSuperSecreta123") - CKV2_AWS_6 — Bucket S3 sem política de bloqueio de acesso público
- CKV_AWS_18 — Bucket S3 sem access logging habilitado
Cada linha do resultado mostra o ID do check, uma descrição, o arquivo e a linha exata do recurso problemático — dá para ir direto ao ponto.
3. Entendendo o output
Formato padrão (texto colorido no terminal):
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: /main.tf:6-15
Guide: https://docs.bridgecrew.io/docs/networking_1
Para integrações e leitura por outras ferramentas, use formatos estruturados:
# JSON — útil para parsing programático
checkov -d . -o json
# JUnit XML — direto em relatórios de CI (GitLab, Jenkins, Azure DevOps)
checkov -d . -o junitxml
# SARIF — formato padrão para GitHub Code Scanning
checkov -d . -o sarif
# Múltiplos formatos ao mesmo tempo, salvando em arquivos
checkov -d . -o cli -o json --output-file-path console,results.json
O exit code também importa em automação: por padrão o Checkov retorna 1 se houver qualquer check FAILED, o que quebra o pipeline — é esse comportamento que você quer como gate de segurança.
4. Corrigindo os problemas
Ajustando o main.tf para resolver os principais achados:
resource "aws_s3_bucket" "data" {
bucket = "minha-empresa-dados-2026"
}
resource "aws_s3_bucket_public_access_block" "data" {
bucket = aws_s3_bucket.data.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
bucket = aws_s3_bucket.data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
}
}
}
resource "aws_security_group" "web" {
name = "web-sg"
description = "Security group da aplicacao web"
ingress {
description = "HTTPS publico"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "SSH restrito a VPN corporativa"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["203.0.113.0/24"]
}
}
resource "aws_db_instance" "main" {
identifier = "app-db"
engine = "mysql"
instance_class = "db.t3.micro"
allocated_storage = 20
username = "admin"
manage_master_user_password = true
storage_encrypted = true
publicly_accessible = false
skip_final_snapshot = false
deletion_protection = true
}
Principais mudanças: bucket com public access block e criptografia; security group sem SSH aberto ao mundo; RDS privado, criptografado, com senha gerenciada pelo Secrets Manager (manage_master_user_password) em vez de hardcoded.
Rode o scan de novo - o número de FAILED deve cair drasticamente:
checkov -d . --compact
5. Suprimindo checks (quando necessário)
Nem todo FAILED é um bug, às vezes é uma decisão consciente (ex: um bucket público de assets estáticos de um site). Para esses casos, suprima o check pontualmente, sempre com justificativa:
resource "aws_s3_bucket" "site_publico" {
bucket = "meu-site-assets-publicos"
# checkov:skip=CKV2_AWS_6:Bucket serve assets estaticos publicos por design (CDN de imagens do site)
}
Para suprimir vários checks em um recurso:
#checkov:skip=CKV_AWS_18:Logging desnecessario neste bucket de teste
#checkov:skip=CKV_AWS_21:Versionamento desnecessario neste bucket de teste
Também é possível ignorar checks globalmente via linha de comando — use com cautela, pois afeta o repositório inteiro:
checkov -d . --skip-check CKV_AWS_8,CKV_AWS_79
Prefira sempre o
#checkov:skipinline no código: fica documentado, versionado e visível em code review, diferente de uma flag de CLI que vive escondida em um script de pipeline.
6. Criando um baseline (para projetos legados)
Ao rodar o Checkov pela primeira vez em um projeto grande e antigo, é comum encontrar centenas de findings acumulados, inviável corrigir tudo de uma vez sem travar o time. A solução é gerar um baseline: um snapshot dos problemas atuais, para que o pipeline falhe só em novos problemas introduzidos daqui pra frente.
# Gera o baseline com o estado atual (findings existentes)
checkov -d . --create-baseline
# Nas próximas execuções, compara contra o baseline
checkov -d . --baseline .checkov.baseline
Isso permite adotar segurança em pipelines de forma incremental, sem bloquear o time por dívida técnica pré-existente.
7. Integração com CI/CD (GitHub Actions)
Exemplo de workflow que roda o Checkov em todo PR que altera arquivos Terraform:
name: Checkov IaC Security Scan
on:
pull_request:
paths:
- '**.tf'
jobs:
checkov:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run Checkov
uses: bridgecrewio/checkov-action@master
with:
directory: .
framework: terraform
output_format: sarif
output_file_path: results.sarif
soft_fail: false
- name: Upload SARIF para GitHub Code Scanning
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
Com soft_fail: false, o job falha e bloqueia o merge se houver check crítico reprovado, esse é o comportamento recomendado para branches protegidas. Use soft_fail: true apenas durante a fase de adoção gradual.
Integração como pre-commit hook
Para pegar problemas antes mesmo do push, adicione ao .pre-commit-config.yaml:
repos:
- repo: https://github.com/bridgecrewio/checkov.git
rev: '3.2.0'
hooks:
- id: checkov
args: ["--compact", "--quiet"]
pip install pre-commit
pre-commit install
8. Checks customizados
Quando as regras padrão não cobrem uma política interna da empresa (ex: "toda instância EC2 deve ter a tag cost-center"), é possível escrever checks próprios.
Custom check em Python:
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
from checkov.common.models.enums import CheckCategories, CheckResult
class EnsureCostCenterTag(BaseResourceCheck):
def __init__(self):
name = "Ensure EC2 instances have a cost-center tag"
id = "CKV_CUSTOM_1"
supported_resources = ["aws_instance"]
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", [{}])[0]
if isinstance(tags, dict) and "cost-center" in tags:
return CheckResult.PASSED
return CheckResult.FAILED
check = EnsureCostCenterTag()
checkov -d . --external-checks-dir ./custom_checks
Custom check em YAML (mais simples, sem precisar de Python):
metadata:
id: "CKV_CUSTOM_2"
name: "Ensure S3 bucket name follows naming convention"
category: "GENERAL_SECURITY"
scope:
provider: "aws"
definition:
and:
- cond_type: "attribute"
resource_types:
- "aws_s3_bucket"
attribute: "bucket"
operator: "starts_with"
value: "empresa-"
9. Referência rápida de flags úteis
| Flag | O que faz |
|---|---|
-d <dir> |
Escaneia todo o diretório recursivamente |
-f <file> |
Escaneia um arquivo específico |
--framework terraform |
Limita o scan a um framework (terraform, kubernetes, dockerfile, etc.) |
--check CKV_AWS_24 |
Roda apenas checks específicos |
--skip-check CKV_AWS_8 |
Ignora checks específicos globalmente |
--compact |
Output resumido, sem detalhes de cada check PASSED
|
--quiet |
Mostra só os FAILED
|
--soft-fail |
Não retorna exit code de erro mesmo com findings |
| `-o json\ | junitxml\ |
{% raw %}--create-baseline
|
Gera baseline com findings atuais |
--external-checks-dir |
Carrega checks customizados |
10. Checkov vs. outras ferramentas
| Ferramenta | Foco | Linguagens suportadas | Diferencial |
|---|---|---|---|
| Checkov | IaC security + compliance | Terraform, CFN, K8s, Helm, Dockerfile, Bicep, Serverless | Maior cobertura de frameworks, análise por grafo |
| tfsec | Terraform security | Apenas Terraform | Muito rápido, focado só em Terraform (hoje integrado ao Trivy) |
| Terrascan | IaC security + compliance | Terraform, K8s, Helm, CFN | Motor baseado em OPA/Rego |
| Trivy | Vulnerabilidades + IaC + containers | IaC, imagens de container, filesystems | Escopo mais amplo (inclui CVEs de pacotes), não só IaC |
Na prática, muitos times usam Checkov + Trivy juntos: Checkov para configuração de IaC, Trivy para vulnerabilidades de imagens de container e dependências. Eles não são mutuamente exclusivos.
Boas práticas
- Rode local antes do commit — pre-commit hook pega o problema em segundos, antes de virar um PR
-
Trave a versão do Checkov no pipeline (
checkov==3.2.0) para evitar que uma nova versão introduza checks que quebrem o build sem aviso - Use baseline em projetos legados — não tente corrigir 300 findings de uma vez, adote incrementalmente
-
Documente todo skip —
#checkov:skipsempre com motivo, nunca silencioso -
Combine com scanning de secrets — o Checkov já detecta segredos em texto plano (
CKV_SECRET_*), mas para repositórios grandes considere complementar comgitleaksno histórico de commits -
Trate achados críticos como bloqueadores —
soft_failé aceitável só durante a fase de adoção, não como estado permanente
Troubleshooting
| Problema | Causa provável | Solução |
|---|---|---|
error: externally-managed-environment no pip install
|
PEP 668 em distros recentes (Debian 12+, Ubuntu 23.04+) | Use pipx install checkov ou um virtualenv |
| Checkov não encontra nenhum recurso | Diretório errado ou .tf com erro de sintaxe |
Rode terraform validate antes; confirme o -d aponta pro diretório certo |
| Check falha mas parece um falso positivo | Contexto que o Checkov não enxerga (ex: recurso protegido por outra camada) | Suprima com #checkov:skip e justificativa, não desabilite globalmente |
| Pipeline trava sempre no primeiro scan | Débito técnico acumulado no repositório | Gere baseline com --create-baseline e adote incrementalmente |
| Scan muito lento em monorepo grande | Escaneando diretórios desnecessários (.terraform/, node_modules/) |
Use --skip-path para excluir pastas irrelevantes |
Conclusão
O Checkov transforma segurança de infraestrutura de uma revisão manual — que depende de alguém lembrar de checar security groups e permissões — em um portão automatizado que roda em segundos, local ou no pipeline. Ele não substitui uma revisão de arquitetura ou um pentest, mas elimina a categoria inteira de erros básicos e repetitivos que hoje são a causa mais comum de incidentes de cloud: bucket público, credencial hardcoded, porta aberta para o mundo.
Comece pequeno: rode checkov -d . no seu projeto Terraform atual, veja o que aparece, gere um baseline se for muito, e adicione como pre-commit hook. Depois de validado localmente, leve para o CI/CD como gate obrigatório em PRs.
Top comments (0)