DEV Community

Cover image for Checkov: Guia Completo de Segurança para Infraestrutura como Código
Luis Cruz
Luis Cruz

Posted on

Checkov: Guia Completo de Segurança para Infraestrutura como Código

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
  • pip disponível
  • Um projeto de IaC para testar (vamos usar Terraform no exemplo)

Verifique sua versão do Python:

python3 --version
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Confirme a instalação:

checkov --version
Enter fullscreen mode Exit fullscreen mode

No Debian/Ubuntu, se pip install checkov reclamar de ambiente gerenciado externamente (PEP 668), use pipx install checkov ou 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
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

Rode o scan apontando para o diretório:

checkov -d .
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Prefira sempre o #checkov:skip inline 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"]
Enter fullscreen mode Exit fullscreen mode
pip install pre-commit
pre-commit install
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode
checkov -d . --external-checks-dir ./custom_checks
Enter fullscreen mode Exit fullscreen mode

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-"
Enter fullscreen mode Exit fullscreen mode

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:skip sempre 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 com gitleaks no histórico de commits
  • Trate achados críticos como bloqueadoressoft_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.


Referências

Top comments (0)