Skip to content
Webhooks SDK
Esc
navigateopen⌘Jpreview
On this page

GitHub

HMAC over the raw body via X-Hub-Signature-256 — pair it with an idempotency store for replay protection.

GitHub signs each delivery with HMAC-SHA256 over the raw body, hex-encoded as sha256=… in X-Hub-Signature-256 (scheme family 1). This covers repository, organization, and GitHub App webhooks.

import { createWebhookHandler, memoryIdempotencyStore } from 'webhooks-sdk'
import { github } from 'webhooks-sdk/github'

const handler = createWebhookHandler({
  provider: github({ secret: process.env.GITHUB_WEBHOOK_SECRET! }),
  idempotency: memoryIdempotencyStore(),
  on: {
    push: async (event) => await deploy(event.payload),
    pull_request: async (event) => await triage(event.payload),
  },
})

export const POST = handler.fetch

Options

Option Type Default
secret string | string[] The webhook secret you set on the hook. Array for rotation.

No timestamp — bring a store

GitHub signs the body alone: the signature proves who sent the request but not when, so the same bytes replayed later verify perfectly. Add an idempotency store — with GitHub it doubles as replay protection.

That’s also why event.id is a digest of the signed body, not the X-GitHub-Delivery GUID: the GUID lives in an unsigned header, so a replay could mint a fresh one and walk straight past id-based deduplication. The delivery GUID stays available for logging:

on: {
  push: async (event) => {
    log('delivery', event.raw.header('x-github-delivery'))
  },
}

The envelope

  • event.type — from the X-GitHub-Event header (push, pull_request, issues, workflow_run, …). Common names autocomplete; any string routes.
  • event.timestamp — receipt time; GitHub sends none on the wire.
  • event.payload — GitHub’s payload, untouched.

Standalone & testing

import {
  verifyGitHubWebhook,  // (raw, { secret }) — throws on failure
  parseGitHubWebhook,   // (raw) — the envelope
  signGitHubWebhook,    // (body, secret) — a valid header value, for tests
} from 'webhooks-sdk/github'

See Standalone verification and Testing.

Was this page helpful?