Segredos no CI/CD: como evitar credenciais em código e logs

Um segredo armazenado fora do repositório ainda pode vazar por logs, actions, runners, artefatos ou permissões excessivas.

Post mortem hipotético: o token não estava no Git, mas apareceu no log Resumo do incidente Uma equipe armazenava o token de produção no mecanismo de secrets da plataforma de CI. O valor nunca foi commitado. Durante uma investigação de falha, uma alteração adicionou modo de depuração ao script de deploy: Logo depois, o script executou uma chamada que incluía o token como argumento. O mecanismo da plataforma mascarou a forma original em parte do log, mas outro passo transformou o valor antes de imprimi lo. A versão codificada não foi reconhecida pelo redactor. O log permaneceu disponível para mais pessoas do que o ambiente de produção. O token possuía: validade de um ano; acesso a múltiplos ambientes; permissão para publicar e remover artefatos; ausência de restrição por repositório; pouca rastreabilidade sobre quem o utilizava. A exposição não dependia de o segredo estar no código. Impacto Como o cenário é hipotético, não há números reais. A análise consideraria: quem podia ler o log; quanto tempo ele ficou disponível; quais recursos o token alcançava; se houve uso fora do padrão; quais artefatos foram publicados; quais credenciais derivadas existiam; quais sistemas confiavam no token. A ausência de evidência de abuso não elimina a necessidade de revogação. Causa técnica O vazamento resultou da combinação de cinco decisões: 1. credencial permanente; 2. escopo excessivo; 3. passagem do segredo como argumento; 4. modo de depuração no job privilegiado; 5. confiança excessiva no mascaramento automático. Causa organizacional O pipeline era tratado como utilitário interno, não como sistema de produção. Alterações em workflows não exigiam revisão especializada. A equipe possuía controles sobre o código da aplicação, mas não sobre o código que carregava as chaves da infraestrutura. A OWASP recomenda tratar ambientes de CI/CD como componentes privilegiados, aplicar mínimo privilégio e preferir credenciais dinâmicas ou de curta duração. O que conta como segredo Exemplos: senha de banco; token de API; chave privada; credencial de nuvem; chave de assinatura; senha SMTP; token de registro; credencial de deploy; segredo de webhook; chave de criptografia; certificado cliente; cookie administrativo. Nem todo dado confidencial é chamado de secret pela ferramenta. Também precisam de proteção: URLs contendo token; arquivos de configuração; planos de infraestrutura; artefatos com credenciais embutidas; dumps; logs; backups; variáveis derivadas. Base64 não é criptografia. Codificar um valor apenas muda sua representação. A ordem preferencial para autenticar um pipeline 1. Não usar segredo Pergunte se a etapa precisa realmente de autenticação. Exemplos: dependência pública; teste local; build que não publica; análise estática; validação de pull request. Um job de teste não precisa receber a identidade de deploy. 2. Usar identidade do workload Quando o provedor suporta OpenID Connect, ou OIDC, o workflow pode provar sua identidade e receber uma credencial temporária. O GitHub documenta que o provedor de destino pode emitir um token de curta duração a partir de claims do job, sem exigir uma chave de nuvem permanente armazenada como secret. Fluxo: A confiança pode considerar: organização; repositório; branch; tag; ambiente; workflow; audiência; identidade do job. OIDC não concede acesso automaticamente. O provedor de destino precisa possuir uma política que aceite apenas identidades previstas. 3. Buscar segredo no momento da execução Quando a aplicação precisa de um valor real, o pipeline pode autenticar se com identidade temporária e buscar o segredo em um cofre. Evite copiar todos os segredos para variáveis globais no início do workflow. 4. Gerar credencial dinâmica Alguns sistemas podem criar: usuário temporário de banco; token com validade de minutos; certificado de curta duração; credencial exclusiva do job. A credencial deixa de ser útil pouco depois da execução. 5. Manter segredo estático somente quando necessário Se o destino não suporta identidade federada ou segredo dinâmico: restrinja o escopo; reduza a validade; use identidade exclusiva; armazene em cofre; automatize rotação; monitore uso; documente dependências. Separação do pipeline por confiança Um desenho mais seguro: Não use as mesmas permissões para: validar contribuição; construir artefato; publicar pacote; alterar produção. O artigo sobre CI/CD seguro detalha essa separação. Exemplo genérico de OIDC no GitHub Actions O exemplo é intencionalmente genérico. Antes de usá lo: substitua FULL COMMIT SHA pelo SHA completo verificado; utilize a action oficial do provedor; restrinja a trust policy; limite a role; proteja o ambiente; fixe qual artefato pode ser implantado. A permissão id token: write permite ao job solicitar o token OIDC. Ela não deveria ser concedida a jobs que não precisam se autenticar externamente. Um secret store não corrige permissão excessiva Compare: com: Mesmo que os dois valores estejam protegidos durante o armazenamento, o impacto de comprometimento é diferente. Mínimo privilégio considera: recurso; ação; ambiente; duração; origem; condição; horário quando apropriado. Segredos por ambiente Use identidades distintas: Ambiente Identidade Alcance Desenvolvimento pipeline dev recursos de desenvolvimento Homologação pipeline hml somente homologação Produção pipeline prod deploy controlado em produção O job de homologação não deve possuir uma variável de produção “sem usar”. A separação de ambientes precisa existir na plataforma de CI, no provedor e na rede. Mascaramento é uma barreira auxiliar No GitHub Actions, valores armazenados como secrets são tratados para ocultação em logs. A documentação também permite registrar valores sensíveis adicionais para mascaramento: Faça isso imediatamente após gerar um valor que possa aparecer posteriormente. Mascaramento possui limites. Ele pode falhar quando o valor é: transformado; dividido; codificado; inserido em estrutura maior; escrito em arquivo; enviado como artefato; impresso por outra ferramenta; desconhecido pela plataforma. Não teste a proteção imprimindo o segredo. Evite: em jobs que manipulam credenciais. Quando diagnóstico detalhado for indispensável, filtre explicitamente e use um ambiente sem segredo real. Argumentos podem aparecer fora do log Comando perigoso: Dependendo do sistema, argumentos podem aparecer em: lista de processos; telemetria; auditoria; mensagens de erro; histórico. Prefira, conforme suporte da ferramenta: entrada por arquivo protegido; descritor; stdin ; agente; integração nativa com cofre; identidade de workload. Variáveis de ambiente também podem ser expostas por ferramentas de diagnóstico. Nenhum meio é automaticamente seguro; reduza quem pode observar o processo. Artefatos e cache não devem transportar credenciais Procure secrets em: imagens de container; layers; bundles frontend; arquivos .env ; pacotes; relatórios de teste; traces; core dumps; planos Terraform; caches de dependência. Um segredo usado durante build pode permanecer em uma camada, mesmo se um comando posterior apagar o arquivo. Use mecanismos de secret mount do builder quando disponíveis e confirme que o valor não aparece no resultado. Nunca envie chave privada para código executado no navegador. Runners próprios ampliam o problema Um self hosted runner comprometido pode preservar: processos; arquivos; credenciais; containers; caches; sockets; ferramentas modificadas. Separe: Não monte indiscriminadamente o socket do Docker. Quem controla o daemon frequentemente consegue alcançar o host. Workflows precisam de owners Arquivo CODEOWNERS : Exija revisão quando uma mudança: amplia permissões; adiciona action; muda gatilho; altera ambiente; lê secrets; muda runner; publica artefato; utiliza pull request target ; modifica trust policy. O code review orientado por risco deve tratar o pipeline como código privilegiado. Rotação precisa ser exercitada Inventário: Segredo Owner Consumidor Validade Rotação Revogação SMTP Plataforma Serviço web 90 dias automatizada provedor Registro CI Job de publicação 30 dias manual registro Banco Aplicação Produção dinâmica automática cofre Para cada segredo, responda: onde é criado; onde é armazenado; quem pode ler; onde é usado; como é rotacionado; como é revogado; o que quebra depois; como detectar uso indevido. Segredo sem owner tende a não ser rotacionado. Procedimento para vazamento 1. Conter desabilitar workflow quando necessário; revogar a credencial; impedir novos usos; restringir acesso ao log; pausar publicações afetadas. Revogar vem antes de limpar o histórico. 2. Preservar evidências horário; job; commit; runner; identidade; IPs; chamadas; artefatos; logs de auditoria. Não apague toda evidência antes da análise. 3. Determinar alcance recursos acessíveis; validade; ações permitidas; sistemas derivados; uso observado. 4. Rotacionar dependências Uma chave pode ter sido usada para obter outras credenciais. 5. Corrigir o vetor remover impressão; reduzir privilégio; migrar para OIDC; tornar runner efêmero; proteger ambiente; adicionar revisão. 6. Verificar artefatos Confirme se imagens, pacotes ou releases foram alterados. 7. Aprender Atualize: teste; política; documentação; scanner; treinamento; runbook. Scanner de segredo não é proteção completa Ferramentas podem encontrar padrões conhecidos antes do merge. Elas não detectam sempre: credencial com formato desconhecido; segredo dividido; valor codificado; acesso concedido por política incorreta; token criado durante execução; segredo em serviço externo. Combine: O NIST SP 800 204D trata o pipeline como parte da cadeia de fornecimento, exigindo controles integrados ao processo DevSecOps. Critério de maturidade Um pipeline protegido permite responder: qual identidade executou; por que recebeu acesso; quanto tempo o acesso durou; qual recurso foi alterado; qual artefato foi publicado; como revogar; onde o uso foi registrado. A meta não é guardar uma senha com mais cuidado. É reduzir a quantidade de senhas permanentes que precisam existir e tornar qualquer credencial restante curta, específica, rastreável e revogável.