capítulo 01
Arquitetura & Threat Model
Três ferramentas, três camadas diferentes do mesmo problema. Antes de configurar qualquer uma, vale entender por que nenhuma delas sozinha seria suficiente.
As três camadas
Um pipeline de code review seguro não é uma ferramenta, é uma composição. Cada gate deste laboratório olha pra um momento diferente do ciclo de vida do código:
- Gitleaks olha pro histórico do Git — cada commit de um PR — procurando padrões de credenciais (chaves de API, tokens, senhas em formato reconhecível).
- SonarCloud olha pro código-fonte em si — análise estática (SAST) do código novo introduzido no PR, sem executar nada.
- OWASP ZAP olha pra aplicação rodando — ataca de fora, como um visitante real faria, sem ter acesso nenhum ao código-fonte.
Na prática deste laboratório, um PR de teste continha uma variável DB_PASSWORD = "supersecret123". O Gitleaks passou limpo — a string não tem entropia suficiente nem bate com nenhum padrão de credencial conhecido. O SonarCloud bloqueou o mesmo PR, porque entende que uma credencial hardcoded no código-fonte é uma prática insegura, independente de a string "parecer" uma chave real. É exatamente esse tipo de lacuna que justifica ter os dois gates, não um só.
O que cada gate resolve — e o que não resolve
| Gate | Resolve | Não resolve | Quando roda |
|---|---|---|---|
| Gitleaks | Segredo vazando pro histórico do Git (chaves, tokens, senhas em formato reconhecível) | Credencial fraca sem formato reconhecível, lógica de negócio insegura, vulnerabilidades em runtime | pre-commit local + toda Pull Request |
| SonarCloud | Code smells, bugs, vulnerabilidades conhecidas no código novo (SQL injection por concatenação, eval(), credenciais hardcoded, cobertura de teste) |
Vulnerabilidades que só aparecem em runtime (configuração do servidor, headers HTTP, comportamento real da aplicação) | Toda Pull Request, avaliando só o código novo |
| OWASP ZAP | Comportamento inseguro da aplicação já rodando: headers de segurança ausentes, configuração de CORS, cookies mal configurados | Não lê o código-fonte, então não aponta onde corrigir — só o quê está exposto | Sob demanda, contra um ambiente com a aplicação de pé |
Por que GitHub Actions + SonarCloud (não self-hosted)
A decisão mais importante de infraestrutura deste laboratório foi não manter nada rodando 24/7. SonarQube self-hospedado exigiria uma VM sempre ligada só pra guardar o histórico de análises; um runner próprio de CI teria o mesmo problema. Usando GitHub Actions (hospedado, gratuito pra repositórios públicos) e SonarCloud (mesma lógica, versão gerenciada do SonarQube), tudo roda sob demanda — o pipeline só "existe" enquanto está executando.
Isso é diferente de um laboratório que precisa receber tráfego real da internet (como um honeypot) — ali, manter algo sempre ligado é parte do requisito. Aqui, o requisito é só provar que o gate funciona, e isso não exige presença constante.
Por que OWASP Juice Shop como alvo
O Juice Shop é o padrão de facto pra demonstrações de AppSec: Node.js, pronto pra rodar em Docker, com vulnerabilidades documentadas e mapeadas ao OWASP Top 10. Isso significa que o gate de DAST (ZAP) tem achados reais garantidos contra ele sem precisar introduzir uma vulnerabilidade artificial — o app já vem assim de propósito, para fins educacionais.
Os dois momentos do pipeline
Os workflows deste repositório estão divididos em dois arquivos, porque representam dois momentos diferentes do ciclo de vida:
pre-merge-gates.yml- Gitleaks + SonarCloud, em toda Pull Request
pre-deploy-dast.yml- OWASP ZAP, disparo manual contra o app já implantado
O segundo workflow não roda a cada push — só sob demanda. O motivo dessa escolha (e o que aconteceu quando ele rodava automaticamente) está detalhado no capítulo 05.