capítulo 04
Troubleshooting
Todo problema abaixo aconteceu de verdade nesta implementação — não são hipóteses. Clique em qualquer sintoma pra ver a causa e a correção.
Gitleaks
Uma chave AWS de teste não dispara nenhum alerta
causa
A string usada foi AKIAIOSFODNN7EXAMPLE — o exemplo oficial de chave de acesso usado em milhares de páginas de documentação da AWS. Justamente por isso, ela está no allowlist interno do próprio Gitleaks: sem essa exceção, qualquer repositório com um trecho de documentação da AWS geraria um falso positivo constante.
correção
Usar qualquer outra string no mesmo formato (AKIA + 16 caracteres), desde que não seja esse valor específico. O restante da configuração não precisa mudar — o allowlist do Gitleaks é sobre esse valor exato, não sobre o padrão inteiro.
Uma chave de teste digitada no terminal chega ao arquivo como bullets (••••••••••••)
causa
Algo no ambiente do terminal mascarava o texto que batia com o padrão de uma AWS Access Key (AKIA + 16 caracteres) no momento da digitação/colagem — antes mesmo de virar conteúdo real do arquivo. Um echo simples nunca mascararia nada por conta própria; a interceptação acontecia em uma camada acima do shell.
correção
Construir a string em duas variáveis de shell separadas e concatená-las só na hora de escrever o arquivo, em vez de digitar/colar o valor completo de uma vez:
p1="AKIA5G3J"
p2="XNQPZ7W2M4KD"
printf 'aws_secret_access_key = "%s%s"\n' "$p1" "$p2" > secret-test.txt
Como nenhum comando isolado contém o padrão completo, o mecanismo de mascaramento não tem o que interceptar.
YAML / GitHub Actions
Um job novo adicionado ao workflow simplesmente não aparece
causa
Indentação incorreta — o novo job (sonarcloud:) foi escrito no mesmo nível das propriedades do job anterior (name:, runs-on:, steps:), em vez de no mesmo nível da própria chave gitleaks:. Em YAML, uma chave-filha precisa de mais indentação que sua chave-pai — com a indentação errada, o parser interpreta tudo como pertencente a um único job, com chaves duplicadas (name, runs-on, steps aparecendo duas vezes).
correção
Validar a estrutura antes de commitar, em vez de confiar só na leitura visual:
python3 -c "import yaml; d=yaml.safe_load(open('arquivo.yml')); print(list(d['jobs'].keys()))"
Se a lista não tiver todos os jobs esperados, é indentação. Reescrever o arquivo inteiro via heredoc (em vez de editar linhas específicas) evita o erro de contar espaços manualmente.
Um comando cat > arquivo << 'EOF' deixa o próprio comando dentro do arquivo
causa
O bloco foi colado em algum lugar que não interpretou o heredoc como comando de shell — por exemplo, dentro de um editor de texto já aberto (nano/vim), em vez do prompt do bash. O resultado é um arquivo cujo conteúdo literal começa com cat > arquivo << 'EOF' e termina com EOF, em vez de conter só o corpo do heredoc.
correção
Rodar o comando completo direto no prompt do terminal (não dentro de um editor já aberto), e validar o resultado antes de commitar. Pra um arquivo de configuração como TOML, um parser real é mais confiável que ler visualmente:
python3 -c "import tomllib; tomllib.load(open('.gitleaks.toml', 'rb')); print('TOML válido')"
OWASP ZAP
Uma regra configurada como FAIL continua aparecendo como WARN-NEW no relatório — mas o job falha do mesmo jeito
causa aparente
A hipótese inicial era que a regra 10038 FAIL no zap-baseline-rules.conf estava escalando aquele achado específico e derrubando o job por causa dele.
causa real
O próprio log da action revela o motivo verdadeiro: "By default ZAP Docker container will fail if it identifies any alerts during the scan!" — com fail_action: true, o job falha se qualquer alerta for encontrado, de qualquer severidade, independente de estar escalado pra FAIL no arquivo de regras. A regra 10038 continuou como WARN-NEW no relatório o tempo todo; o arquivo de regras, como estava escrito, não teve efeito nenhum no resultado.
correção
Nenhuma mudança de configuração foi necessária — só o entendimento correto: pra esse cenário, fail_action: true sozinho já garante o bloqueio. O arquivo de regras continua útil pra decidir o que ignorar (IGNORE), não pra decidir o que causa falha.
gh run view --log devolve "logs will be available when it is complete"
causa
Não é um erro — o run ainda está em execução. Um scan do ZAP demora bem mais que os gates de Gitleaks/SonarCloud (1 a 3 minutos), então é fácil pedir o log cedo demais.
correção
Esperar o run terminar antes de pedir o log:
gh run watch $RUN_ID
Design do pipeline
O workflow de DAST deixa o repositório permanentemente "vermelho" no Actions
causa
O workflow disparava em todo push pra master, mas o alvo (Juice Shop) sempre tem os mesmos achados reais — então todo commit, mesmo sem relação nenhuma com o pipeline, terminava em falha. O gate estava funcionando corretamente; o sinal visual é que ficava enganoso, sugerindo "pipeline quebrado" pra quem olhasse de fora.
correção
Trocar o gatilho de push: branches: [master] pra workflow_dispatch (disparo manual). Mais detalhes sobre por que isso reflete melhor como DAST funciona na prática estão no capítulo 05.