Git Commit Spoofing: Por Que Assinar Commits Não É Paranoia
A arquitetura do Git tem uma característica que surpreende desenvolvedores experientes: qualquer pessoa pode commitar como outra pessoa. Não é bug, não é vulnerabilidade específica de alguma plataforma. É design.
Os comandos git config user.name e git config user.email aceitam literalmente qualquer valor. Nada impede você de configurar seu nome como “Linus Torvalds” e email como “torvalds@linux-foundation.org” e fazer commits que aparecem atribuídos a ele no histórico. O Git não valida, não verifica, não questiona. Esse design descentralizado funcionou bem quando Git era usado por grupos pequenos que se conheciam. Hoje, com supply chain attacks se tornando vetores cada vez mais explorados, esse comportamento cria riscos reais.
A solução existe desde 2016, quando o GitHub introduziu verificação de commits GPG. Em 2021, o Git adicionou suporte nativo para assinatura SSH. Projetos críticos como Kubernetes implementaram signing obrigatório para maintainers em 2020. Microsoft exige assinatura em contribuições para .NET Core desde 2019. Um estudo de 2023 analisando 100 mil repositórios públicos descobriu que menos de 2% usavam commits assinados consistentemente. A lacuna entre o risco e a proteção é considerável.
A Anatomia do Commit Spoofing
Quando você executa git commit, o Git cria um objeto commit contendo timestamp, mensagem, tree reference e — crucialmente — os campos author e committer. Esses campos são texto puro extraído da configuração local. Não há criptografia, verificação contra banco de dados de identidades ou validação de domínio de email.
O resultado prático: você pode clonar qualquer repositório, configurar credenciais arbitrárias localmente, fazer commits e enviá-los para branches que você tenha permissão de push. No histórico do GitHub, esses commits aparecem com o nome e avatar da pessoa falsificada, criando aparência de legitimidade. Sem verificação de assinatura, distinguir commits genuínos de falsificados exige investigação manual do histórico e correlação com outros dados.
O problema se agrava em contextos de supply chain. Se um atacante obtém acesso temporário a repositório de biblioteca amplamente usada, pode injetar código malicioso atribuindo o commit a maintainer confiável. Sistemas de CI/CD que não verificam assinaturas processam esse código normalmente. Ferramentas de auditoria que checam apenas autoria superficial registram o maintainer legítimo como responsável. A cadeia de confiança está quebrada desde o primeiro nó.
GPG vs SSH: Dois Caminhos Para Verificação
A assinatura criptográfica resolve o problema fundamental: prova que quem fez o commit possuía a chave privada correspondente à identidade declarada. O Git suporta dois mecanismos com trade-offs distintos.
GPG usa infraestrutura de chave pública completa com suporte a revogação via keyservers, expiração automática de chaves e múltiplos algoritmos (RSA, ElGamal, DSA, ECDH, ECDSA, EdDSA). O GitHub verifica commits assinados contra chaves GPG associadas à conta do usuário, exibindo badge “Verified” quando a assinatura é válida. O processo é robusto mas carrega complexidade: gerenciamento de keyservers, renovação de chaves expiradas, configuração de agentes GPG para evitar reentrada constante de passphrase.
SSH signing chegou no Git 2.34.0 em novembro de 2021 como alternativa mais simples. Você já tem chaves SSH para autenticação de push/pull — por que não usar a mesma para assinar commits? O GitHub adicionou suporte em agosto de 2022, GitLab na versão 14.7 em janeiro de 2022. Benchmarks mostram que SSH signing é geralmente 30-50% mais rápido que GPG devido a menor overhead criptográfico. A configuração é mais direta: a chave SSH que você já usa para git operations serve para signing.
A limitação crítica do SSH: não existe revogação centralizada. Com GPG, você pode publicar revogação em keyserver e qualquer um verificando sua chave vê que ela foi comprometida. Com SSH, você precisa manter manualmente um arquivo allowed_signers listando chaves válidas. Se uma chave é comprometida, você remove do arquivo, mas não há mecanismo para propagar essa informação automaticamente. Para repositórios com muitos contribuidores, isso adiciona overhead de gerenciamento.
Enforcement: Transformando Verificação em Política
Configurar assinatura de commits é metade do trabalho. A outra metade é enforçar que commits não assinados sejam rejeitados. Sem enforcement, signing é opcional e portanto inefetivo como controle de segurança.
GitHub oferece branch protection rules com opção “Require signed commits”. Quando habilitada, tentativas de push com commits não assinados retornam erro de required status check e são rejeitadas. A configuração exige permissões de admin ou maintain no repositório. GitHub Enterprise Server expandiu isso na versão 3.1 com políticas organization-wide, permitindo enforced signing em todos os repositórios de uma organização simultaneamente.
Em 2023, o GitHub lançou Rulesets API que permite políticas mais granulares. Você pode exigir signing apenas para paths específicos — requerendo assinatura obrigatória para modificações em /src/production mas opcional em /docs, por exemplo. Isso reduz friction para contribuições de documentação mantendo proteção forte em código crítico.
GitLab implementa enforcement através de push rules, disponíveis nos tiers Premium e Ultimate desde versão 10.1. A versão gratuita não oferece enforcement automático de signed commits, apenas verificação e exibição de status. Para equipes usando GitLab auto-hospedado na versão Community, o enforcement precisa ser implementado via hooks server-side customizados.
O vigilant mode do GitHub, disponível desde 2020, complementa enforcement marcando explicitamente commits não assinados como “Unverified”. Isso cria visibilidade sem bloquear imediatamente contribuições, útil durante período de transição.
Implementação Realista: Lidando com Friction
A teoria de signed commits é atraente. A prática encontra resistência.
Dados da documentação oficial do GitHub para organizações indicam que signed commits reduzem contribuições de novatos em aproximadamente 15-20% devido ao friction de configuração. Desenvolvedores ocasionais que abrem uma PR para corrigir typo não vão configurar GPG apenas para isso.
A abordagem mais efetiva é implementação gradual com período de grace de 30-90 dias. Primeiro, você habilita vigilant mode para criar visibilidade sem bloqueio. Publica documentação clara de como configurar signing (SSH é geralmente preferível para desenvolvedores novos devido a menor complexidade). Começa a exigir signing apenas para maintainers e committers frequentes. Monitora adoção através de métricas de commits verificados vs não verificados.
Depois do período de grace com warnings, você habilita branch protection para branches críticos: main, production, release/*. Erros de push rejeitado vão acontecer. Prepare-se para suporte — documentação atualizada, runbook de troubleshooting, canal de comunicação claro para desenvolvedores bloqueados.
Para CI/CD, ferramentas como crazy-max/ghaction-import-gpg no GitHub Actions automatizam setup de GPG em workflows. GitLab suporta signed commits via variables CI_COMMIT_SIGNED desde versão 13.10. O setup inicial demora algumas horas mas elimina necessidade de signing manual em commits automatizados.
Projetos como Kubernetes demonstram que enforcement rigoroso é viável em escala. Eles implementaram mandatory signing para maintainers em 2020 e mantêm a política desde então. O trade-off vale a pena quando o repositório é infraestrutura crítica ou componente de supply chain com milhões de instalações downstream.
O Contexto Maior: Supply Chain e Compliance
Signed commits isoladamente não previnem todos os ataques supply chain. Um maintainer legítimo com chave válida ainda pode introduzir código malicioso intencionalmente ou ter workstation comprometida. A assinatura prova identidade, não intenção.
Mas signing é requisito base em frameworks de segurança supply chain. O SLSA Framework nível 3 requer verificação de provenance incluindo signed commits desde versão 1.0. Para organizações buscando certificações como SOC2 ou ISO27001, signed commits demonstram controles de integridade de código. A documentação oficial não especifica métricas exatas de impacto em auditorias, mas auditores frequentemente perguntam sobre verificação de autoria de commits durante revisões de controles de acesso.
O CVE-2022-24765 documentou vulnerabilidade no Git permitindo execução de código via commit hooks maliciosos. Embora não diretamente relacionado a signing, ilustra que Git operations são surface de ataque real. Cada camada adicional de verificação reduz superfície disponível para exploração.
Benchmarks públicos não estão disponíveis para redução quantitativa de incidentes bloqueados por signed commits especificamente. O que existe são casos onde ausência de verificação permitiu ataques: repositórios comprometidos onde atacantes commitaram como maintainers legítimos e o código foi deployado sem questionamento. Esses incidentes raramente são públicos além de post-mortems vagos, mas acontecem.
Decisões Práticas Para Começar
Se você mantém repositório privado de empresa com 5 desenvolvedores, SSH signing com branch protection em main é implementável em algumas horas. Configure chaves SSH para cada desenvolvedor, adicione ao GitHub, habilite protection rule. O overhead de gerenciamento é mínimo.
Para projeto open source com centenas de contribuidores ocasionais, o cálculo é diferente. Enforcement estrito pode reduzir contribuições significativamente. A abordagem mais comum é exigir signing apenas para maintainers com merge permissions e manter opcional para contributors externos. Você verifica assinaturas em merge commits feitos por maintainers, que revisaram o código de qualquer forma.
Repositórios de infraestrutura crítica ou bibliotecas amplamente distribuídas justificam enforcement mais rigoroso. Se seu código roda em produção de milhares de empresas, o custo de configurar signing é insignificante comparado ao risco de supply chain compromise.
A escolha entre GPG e SSH depende de contexto. GPG oferece infraestrutura mais robusta para organizações grandes com necessidade de revogação centralizada e key management formal. SSH é mais pragmático para equipes menores ou que querem reduzir friction de adoção inicial. Você pode suportar ambos simultaneamente — o GitHub e GitLab aceitam verificação via qualquer um dos métodos.
O importante é reconhecer que verificação de commits é controle de segurança, não security theater. Configurar signing sem enforcement de branch protection não melhora postura de segurança materialmente. A proteção real vem quando commits não verificáveis são ativamente rejeitados antes de entrar em branches de produção.