SAST e DAST: Fundamentos e Diferenças
A segurança de aplicações é um dos pilares mais críticos do desenvolvimento moderno. Existem duas abordagens fundamentais para identificar vulnerabilidades: SAST (Static Application Security Testing) e DAST (Dynamic Application Security Testing). Compreender a diferença entre elas é essencial para construir uma estratégia de segurança eficaz em seus pipelines de CI/CD.
SAST analisa o código-fonte, bytecode ou binários sem executar a aplicação. É como revisar um livro antes de publicá-lo, procurando por erros estruturais. DAST, por outro lado, testa a aplicação em execução, simulando ataques reais contra a aplicação rodando. É como testar um carro em uma pista, verificando como ele se comporta sob pressão. Ambas são complementares: SAST encontra problemas cedo no desenvolvimento, enquanto DAST identifica vulnerabilidades que só aparecem em tempo de execução ou em contextos específicos de produção.
A integração de ambas em pipelines de CI/CD cria uma camada dupla de proteção. Você consegue bloquear código vulnerável antes mesmo de fazer deploy, e também valida a segurança da aplicação já rodando. Neste artigo, vamos explorar as ferramentas mais populares e como integrá-las adequadamente.
Trivy: SAST Leve e Focado em Containers
O Trivy é uma ferramenta SAST desenvolvida pela Aqua Security que se destacou por sua leveza e velocidade. Ela foi projetada originalmente para varrer imagens de container, mas evoluiu para detectar vulnerabilidades em código-fonte, dependências e configurações. A grande vantagem do Trivy é a simplicidade: ele funciona com um único comando e integra perfeitamente em qualquer pipeline.
O Trivy mantém um banco de dados local de vulnerabilidades conhecidas (CVEs) que é atualizado automaticamente. Ele consegue identificar problemas em dependências do Python, Node.js, Go, Java e muitas outras linguagens. Para começar, basta instalar e executar:
# Instalação no Ubuntu/Debian
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | apt-key add -
echo "deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | tee -a /etc/apt/sources.list.d/trivy.list
apt-get update && apt-get install trivy
# Escanear um repositório local
trivy fs --severity HIGH,CRITICAL ./seu-projeto
# Escanear uma imagem Docker
trivy image nginx:latest
# Gerar relatório em JSON para integração
trivy fs --format json --output results.json ./seu-projeto
A integração em um pipeline GitLab CI/CD é direta:
# .gitlab-ci.yml
stages:
- security
trivy-scan:
stage: security
image: aquasec/trivy:latest
script:
- trivy fs --severity HIGH,CRITICAL --exit-code 1 .
artifacts:
reports:
sast: trivy-results.json
when: always
O --exit-code 1 força a falha do job se vulnerabilidades críticas ou altas forem encontradas. Isso impede que código vulnerável chegue ao repositório principal. Você pode ajustar o nível de severidade conforme sua política de segurança. O Trivy também suporta análise de secrets (senhas expostas), o que é particularmente útil para evitar credenciais no repositório.
SonarQube: SAST Profundo com Qualidade de Código
O SonarQube é uma plataforma enterprise de análise de código que vai além de segurança. Ele combina SAST com análise de qualidade de código, identificando bugs, code smells, duplicações e vulnerabilidades. É especialmente poderoso para projetos grandes onde você precisa manter controle sobre múltiplos aspectos da qualidade.
SonarQube funciona em modo cliente-servidor. Você executa um scanner que envia os resultados para um servidor central, que processa e exibe os dados em um dashboard. A cobertura de linguagens é impressionante: Java, Python, JavaScript, C#, C++, Go, PHP, Swift, Kotlin e muitas outras. Para vulnerabilidades de segurança, o SonarQube usa regras que cobrem o OWASP Top 10 e CWE (Common Weakness Enumeration).
Configurar o SonarQube envolve dois passos: instalar o servidor e configurar o scanner em seu pipeline. Para começar com Docker:
# Iniciar servidor SonarQube (versão community)
docker run -d --name sonarqube \
-p 9000:9000 \
sonarqube:latest
# Acessar em http://localhost:9000 (usuário: admin, senha: admin)
Agora, configure o scanner em seu projeto. Primeiro, instale o SonarScanner:
# Instalação do SonarScanner (macOS com Homebrew)
brew install sonar-scanner
# Ou no Linux, baixe a versão apropriada
wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.8.0.2856-linux.zip
unzip sonar-scanner-cli-4.8.0.2856-linux.zip
Crie um arquivo sonar-project.properties na raiz do projeto:
sonar.projectKey=meu-app
sonar.projectName=Minha Aplicação
sonar.projectVersion=1.0.0
sonar.sources=src
sonar.exclusions=**/*Test.java,**/node_modules/**
sonar.host.url=http://localhost:9000
sonar.login=seu_token_aqui
Execute o scanner:
sonar-scanner
Para integração em GitHub Actions:
name: SonarQube Analysis
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
sonar:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: sonarsource/sonarqube-scan-action@master
env:
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- uses: sonarsource/sonarqube-quality-gate-action@master
timeout-minutes: 5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
O SonarQube é particularmente útil quando você precisa de análise contínua e histórico de métricas. O dashboard mostra tendências de segurança e qualidade ao longo do tempo, facilitando decisões arquiteturais.
OWASP ZAP: DAST Dinâmico e Interativo
Enquanto SAST analisa código estático, OWASP ZAP (Zed Attack Proxy) é um DAST que testa a aplicação em execução. O ZAP simula ataques reais contra endpoints HTTP, verificando vulnerabilidades como SQL Injection, XSS, CSRF, insecurança em autenticação e muitos outros vetores que só aparecem quando a aplicação está rodando.
O ZAP funciona como um proxy man-in-the-middle (MITM), interceptando requisições e respostas. Ele pode fazer testes passivos (apenas observando tráfego) ou ativos (enviando payloads maliciosos para tentar explorar vulnerabilidades). O OWASP ZAP é gratuito e open-source, com suporte extenso da comunidade.
Existem dois modos principais de usar ZAP: modo GUI (para exploração manual) e modo CLI (para automação em pipelines). Para CI/CD, o modo CLI é mais apropriado. Instale o ZAP:
# No Ubuntu/Debian
sudo apt-get install zaproxy
# Ou via Docker (recomendado para pipelines)
docker run --rm -t owasp/zap2docker-stable zap-baseline.py -t http://seu-app.local
Exemplo de teste baseline com Docker:
#!/bin/bash
# Script para DAST com ZAP
# Inicia a aplicação em background
docker run -d --name app-test -p 8080:8080 seu-app:latest
# Aguarda a aplicação ficar pronta
sleep 10
# Executa ZAP baseline (menos agressivo, mais rápido)
docker run --rm --network host \
-v $(pwd):/zap/wrk:rw \
owasp/zap2docker-baseline:latest \
zap-baseline.py \
-t http://localhost:8080 \
-r report.html \
-J report.json
# Para teste mais profundo, use zap-full-scan.py ao invés
# Limpa
docker stop app-test
docker rm app-test
# Valida resultados (falha se HIGH ou CRITICAL encontrado)
if grep -q '"risk":"High"' report.json || grep -q '"risk":"Critical"' report.json; then
exit 1
fi
Integração em GitHub Actions com ZAP:
name: OWASP ZAP DAST
on:
push:
branches: [ main ]
schedule:
- cron: '0 2 * * 0' # Executar às 2AM aos domingos
jobs:
zap-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Start application
run: |
docker-compose -f docker-compose.test.yml up -d
sleep 15
- name: Run ZAP Scan
uses: zaproxy/action-baseline@v0.7.0
with:
target: 'http://localhost:8080'
rules_file_name: '.zap/rules.tsv'
cmd_options: '-a'
- name: Upload ZAP results
if: always()
uses: actions/upload-artifact@v3
with:
name: zap-report
path: report_html.html
O ZAP é ideal para testes em ambientes de staging antes de produção. Você consegue detectar vulnerabilidades de lógica de negócio, autenticação quebrada e ataques específicos do contexto da aplicação.
Snyk: SAST Especializado em Dependências
O Snyk é uma plataforma focada em encontrar e corrigir vulnerabilidades em dependências e container images. Enquanto Trivy é mais genérico, Snyk oferece análise mais profunda de bibliotecas, com insights sobre severidade, exploitabilidade real e patches disponíveis. É particularmente forte em ecossistemas como npm, pip, Maven e Gemfile.
Snyk combina dados de múltiplas fontes de vulnerabilidades (NVD, GHSA, banco próprio) para oferecer um quadro mais completo. Além de identificar CVEs, o Snyk verifica se há patches disponíveis e sugere versões seguras imediatamente. A plataforma também integra com repositórios Git, oferecendo pull requests automáticos para patches de segurança.
Instale e configure o Snyk CLI:
# Instalação via npm
npm install -g snyk
# Autenticar com sua conta Snyk
snyk auth
# Testar vulnerabilidades em um projeto
snyk test
# Monitorar continuamente (cria webhook no Git)
snyk monitor
# Testar apenas dependências diretas (excluindo transitivas)
snyk test --strict-out-of-sync=false
Exemplo de uso em um projeto Python:
# Criar um ambiente virtual
python -m venv venv
source venv/bin/activate
# Instalar dependências
pip install -r requirements.txt
# Testar com Snyk
snyk test --file=requirements.txt
# Gerar relatório em JSON
snyk test --json > snyk-report.json
Integração em GitHub Actions:
name: Snyk Security
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
snyk:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Snyk to check for vulnerabilities
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high
- name: Upload results to Snyk
uses: snyk/actions/setup@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
run: snyk monitor
Uma das melhores características do Snyk é a integração automática com repositórios. Você pode configurar Snyk para criar pull requests automaticamente quando patches estão disponíveis:
# Criar token API no dashboard Snyk
# Conectar repositório via https://app.snyk.io
# Snyk gerará PRs automáticas quando:
# - Novos patches forem lançados
# - Novas vulnerabilidades forem descobertas
# - Dependências transitivas forem atualizadas
Snyk é especialmente valioso em ambientes com muitas dependências, onde gerenciar patches manualmente seria impraticável.
Orquestração Integrada: Pipeline Completo
Integrar SAST e DAST em um pipeline único garante cobertura completa. O ideal é executar SAST rapidamente (bloqueia código ruim antes) e DAST em um ambiente mais controlado (testa a aplicação rodando). Aqui está um exemplo realista de pipeline GitLab CI/CD que integra todas as ferramentas:
# .gitlab-ci.yml - Pipeline completo SAST + DAST
stages:
- build
- sast
- docker
- deploy-staging
- dast
- cleanup
variables:
REGISTRY: registry.gitlab.com
IMAGE_NAME: $REGISTRY/$CI_PROJECT_PATH
build:
stage: build
image: python:3.11
script:
- pip install -r requirements.txt
- python -m pytest tests/ --cov=src
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage.xml
trivy-fs:
stage: sast
image: aquasec/trivy:latest
script:
- trivy fs --severity HIGH,CRITICAL --format json --output trivy-fs.json .
- trivy fs --severity HIGH,CRITICAL .
artifacts:
reports:
sast: trivy-fs.json
when: always
sonarqube:
stage: sast
image: sonarsource/sonar-scanner-cli:latest
script:
- sonar-scanner
-Dsonar.projectKey=$CI_PROJECT_NAME
-Dsonar.sources=src
-Dsonar.host.url=$SONAR_HOST_URL
-Dsonar.login=$SONAR_TOKEN
only:
- merge_requests
- main
snyk-test:
stage: sast
image: snyk/snyk:python-3.11
script:
- snyk test --severity-threshold=high
env:
SNYK_TOKEN: $SNYK_TOKEN
allow_failure: true
docker-build:
stage: docker
image: docker:latest
services:
- docker:dind
script:
- docker build -t $IMAGE_NAME:$CI_COMMIT_SHA .
- docker tag $IMAGE_NAME:$CI_COMMIT_SHA $IMAGE_NAME:latest
- docker push $IMAGE_NAME:$CI_COMMIT_SHA
- docker push $IMAGE_NAME:latest
trivy-image:
stage: docker
image: aquasec/trivy:latest
script:
- trivy image --severity HIGH,CRITICAL --format json --output trivy-image.json $IMAGE_NAME:$CI_COMMIT_SHA
- trivy image --severity HIGH,CRITICAL $IMAGE_NAME:$CI_COMMIT_SHA
dependencies:
- docker-build
artifacts:
reports:
container_scanning: trivy-image.json
when: always
deploy-staging:
stage: deploy-staging
image: bitnami/kubectl:latest
script:
- kubectl set image deployment/app app=$IMAGE_NAME:$CI_COMMIT_SHA -n staging
- kubectl rollout status deployment/app -n staging
environment:
name: staging
url: https://staging.seu-app.com
only:
- main
zap-baseline:
stage: dast
image: owasp/zap2docker-stable:latest
script:
- sleep 30 # Aguarda deploy estar ready
- zap-baseline.py
-t https://staging.seu-app.com
-r report.html
-J report.json
-a # Enable all scanners
artifacts:
paths:
- report.html
- report.json
reports:
sast: report.json
when: always
allow_failure: true
only:
- main
cleanup-staging:
stage: cleanup
script:
- echo "Cleanup stage"
when: always
Este pipeline segue uma ordem lógica: primeiro valida o código (build + testes), depois executa SAST em paralelo (Trivy, SonarQube, Snyk), constrói a imagem Docker e a escaneia, deploya em staging, e finalmente executa DAST contra a aplicação rodando.
Conclusão
Você aprendeu que SAST e DAST são complementares, não substitutos. SAST (Trivy, SonarQube, Snyk) encontra problemas no código e dependências antes da execução, enquanto DAST (OWASP ZAP) testa vulnerabilidades em tempo de execução. A combinação delas em um pipeline CI/CD cria uma defesa em profundidade que bloqueia a maioria dos riscos de segurança.
A escolha de ferramentas deve considerar o contexto: Trivy é leve e rápido para verificações simples, SonarQube é enterprise com histórico e controle fino, Snyk é especializado em dependências com patches automáticos, e OWASP ZAP é essencial para validar comportamento em runtime. Um pipeline maduro integra todas, mas nem todas as organizações precisam de todas simultaneamente.
Por fim, segurança é um processo contínuo. As ferramentas apenas alertam; cabe aos desenvolvedores e arquitetos entender as vulnerabilidades reportadas, priorizar baseado em risco real (não apenas score CVSS), e manter dependências atualizadas. Automação é essencial, mas contexto humano é insubstituível.