Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Quando trabalhamos com integrações usando webhooks do GitHub, um dos pontos mais críticos é garantir que as solicitações recebidas sejam legítimas. Isso se dá através da assinatura do payload com um segredo compartilhado, usando HMAC SHA1. No entanto, muitas vezes, mesmo com o código aparentemente correto, a assinatura gerada nunca bate com a enviada pelo GitHub, causando frustração e dúvidas.
O cenário comum envolve uma aplicação que recebe webhooks do GitHub, protegidos por uma assinatura no cabeçalho X-Hub-Signature. Apesar de seguir a documentação oficial, o hash calculado na aplicação nunca corresponde ao enviado pelo serviço, levando a uma rejeição constante.
O erro geralmente ocorre por uma má interpretação do modo como o payload deve ser tratado na geração do hash. GitHub calcula a assinatura utilizando o corpo exato da requisição, incluindo qualquer formatação, sem modificações ou serializações adicionais. Assim, a tentativa de gerar o hash a partir de um JSON.stringify() ou buffer pode resultar em diferenças sutis que invalidam a assinatura. Sem esse critério, a solução pode parecer simples no começo e cara no suporte. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco.
Outro ponto que pesa é o cabeçalho enviado: 'sha1=' seguido do valor hex da assinatura. Para a validação, o valor do header deve ser comparado exatamente com o hash calculado, após garantir que ambos estão usando o mesmo conteúdo e codificação. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco.
Para evitar inconsistências, o ideal é trabalhar com o corpo bruto da requisição, exatamente como o GitHub o enviou. Em ambientes Node.js, isso significa configurar o middleware do servidor para capturar o corpo como buffer bruto, sem parseá-lo automaticamente. Por isso, o recorte precisa considerar manutenção, validação e caminho de volta. Esse contexto ajuda a separar ganho real de novidade difícil de sustentar. A decisão fica mais saudável quando o time consegue medir o impacto depois. Sem esse critério, a solução pode parecer simples no começo e cara no suporte. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco.
Por exemplo:
const crypto = require('crypto'). // Configurar o servidor para receber o corpo como buffer
app.use(express.raw({ type: 'application/json' })). app.post('/webhook', (req, res) => {
const signature = req.headers['x-hub-signature']. const secret = process.env.GITHUB_SECRET. const payload = req.body. // Buffer bruto
const hmac = crypto.createHmac('sha1', secret). hmac.update(payload). const digest = 'sha1=' + hmac.digest('hex'). if (signature === digest) {
// Assinatura válida
res.status(200).send('Webhook recebido com assinatura válida'). } else {
// Assinatura inválida
res.status(403).send('Assinatura inválida'). }
}).
Assim, a assinatura é gerada exatamente com o conteúdo recebido, evitando diferenças causadas por serializações ou outros processos.
Essa abordagem exige que o servidor não processe o corpo da requisição até o momento da validação, o que pode impactar a manipulação de payloads em alguns frameworks. Além disso, é importante garantir que o método de captura do corpo seja consistente em toda a aplicação. Sem esse critério, a solução pode parecer simples no começo e cara no suporte. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco. Por isso, o recorte precisa considerar manutenção, validação e caminho de volta. Esse contexto ajuda a separar ganho real de novidade difícil de sustentar. A decisão fica mais saudável quando o time consegue medir o impacto depois. Sem esse critério, a solução pode parecer simples no começo e cara no suporte.
Por outro lado, trabalhar com o corpo bruto elimina ambiguidades na assinatura, garantindo maior segurança na validação. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco. A decisão fica mais saudável quando o time consegue medir o impacto depois. Sem esse critério, a solução pode parecer simples no começo e cara no suporte. A decisão fica mais saudável quando o time consegue medir o impacto depois. A decisão fica mais saudável quando o time consegue medir o impacto depois. A decisão fica mais saudável quando o time consegue medir o impacto depois. A decisão fica mais saudável quando o time consegue medir o impacto depois. Sem esse critério, a solução pode parecer simples no começo e cara no suporte.
1. Configurar o middleware para capturar o corpo como buffer bruto.
2. Garantir que o segredo esteja corretamente configurado e acessível.
3. Calcular o HMAC SHA1 usando o corpo bruto exatamente como recebido.
4. Comparar a assinatura gerada com a do cabeçalho, sem modificações.
Validar webhooks do GitHub com SHA1 pode parecer simples, mas exige atenção ao tratamento do payload. A chave é trabalhar com o corpo na sua forma original, evitando alterações que invalidem o hash. Assim, a segurança da integração é reforçada e o problema de assinaturas que nunca batem é resolvido de forma prática. Por isso, o recorte precisa considerar manutenção, validação e caminho de volta. Sem esse critério, a solução pode parecer simples no começo e cara no suporte. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco. Sem esse critério, a solução pode parecer simples no começo e cara no suporte. Sem esse critério, a solução pode parecer simples no começo e cara no suporte.
Se você já passou por isso, sabe que ajustar o tratamento do corpo é um passo decisivo. Essa abordagem, embora exija atenção na configuração do servidor, traz mais confiabilidade na validação e evita erros comuns que aparecem na rotina de integração. Esse contexto ajuda a separar ganho real de novidade difícil de sustentar. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco. O valor aparece melhor quando operação, produto e engenharia olham para o mesmo risco.
No meu time, já vi gente se perder na hora de usar JSON.stringify() e acabar invalidando a assinatura. Trabalhar com o buffer bruto realmente faz toda a diferença.
Exato. Acho que o maior erro é achar que o JSON é exatamente o conteúdo enviado pelo GitHub. Na prática, o buffer mantém a integridade.
E ainda tem que ficar de olho na configuração do middleware pra não parsear o corpo automaticamente. Essa parte às vezes passa batida.