GitHub Webhooks - Reference

Cheatsheet Git

Security headers, events, testing, and setup guide for GitHub webhooks

What is this? Official Docs

Event notification system that triggers HTTP callbacks when repository events occur on GitHub.

What is GitHub Webhooks?

GitHub Webhooks allow you to receive real-time HTTP notifications when events occur in your repositories. This reference guide covers security headers, event types, testing methods, and setup instructions for implementing webhooks.

⚑ Key Features

  • Security header validation
  • Event type reference
  • Testing with ngrok and cURL
  • GitHub configuration steps
  • Production best practices

🎯 Use Cases

  • Webhook setup and testing
  • Security implementation
  • Event payload reference
  • Troubleshooting guides
  • Production deployment

πŸ” Security Headers

GitHub sends these headers with each webhook request.

HeaderDescription
X-GitHub-EventEvent type (push, pull_request, etc.)
X-Hub-Signature-256HMAC SHA-256 signature for verification
X-GitHub-DeliveryUnique delivery ID
User-AgentAlways starts with GitHub-Hookshot/

βœ… Signature Verification Steps

How to verify GitHub webhook signatures securely.

  1. Read raw request body
  2. Compute HMAC SHA-256 with your secret
  3. Compare with X-Hub-Signature-256 header
  4. Use constant-time comparison to prevent timing attacks

Why it matters:

  • Prevents unauthorized webhook calls
  • Ensures request is from GitHub
  • Protects against replay attacks

πŸ“Œ Common Events

GitHub webhook event types and their triggers.

EventTrigger
pushCode pushed to repository
pull_requestPR opened, closed, or updated
issuesIssue created or modified
releaseRelease published
workflow_runGitHub Actions workflow completed
createBranch or tag created
deleteBranch or tag deleted
forkRepository forked
starRepository starred
watchRepository watched

πŸ“¦ Event Payloads

Example payload structures for common events.

Push Event

{
  "ref": "refs/heads/main",
  "before": "abc123...",
  "after": "def456...",
  "repository": {
    "name": "my-repo",
    "full_name": "user/my-repo"
  },
  "pusher": {
    "name": "username",
    "email": "user@example.com"
  },
  "commits": [...]
}

Pull Request Event

{
  "action": "opened",
  "number": 42,
  "pull_request": {
    "title": "Fix bug",
    "state": "open",
    "user": {"login": "username"},
    "head": {"ref": "feature-branch"},
    "base": {"ref": "main"}
  }
}

🌐 Testing - ngrok

Expose local server for webhook testing.

# Install ngrok
# Download from https://ngrok.com/download

# Expose local server
ngrok http 3000

# Copy HTTPS URL to GitHub webhook settings
# Example: https://abc123.ngrok.io/webhook

Alternative: Use GitHub webhook delivery tab to redeliver past events

πŸ”§ Testing - Manual cURL

Test webhook handler with cURL.

curl -X POST http://localhost:3000/webhook \
  -H "X-GitHub-Event: push" \
  -H "X-Hub-Signature-256: sha256=YOUR_SIG" \
  -H "Content-Type: application/json" \
  -d '{"ref":"refs/heads/main"}'

Generate valid signature:

echo -n '{"ref":"refs/heads/main"}' | \
  openssl dgst -sha256 -hmac "your_secret"

πŸ“ Testing - Payload Examples

Save test payloads for different events.

push-event.json:

{
  "ref": "refs/heads/main",
  "repository": {
    "name": "test-repo",
    "full_name": "user/test-repo"
  },
  "pusher": {
    "name": "testuser"
  }
}

Test with file:

curl -X POST http://localhost:3000/webhook \
  -H "X-GitHub-Event: push" \
  -H "Content-Type: application/json" \
  -d @push-event.json

βš™οΈ Setup - GitHub Configuration

Configure webhook in GitHub repository.

Steps:

  1. Go to Settings β†’ Webhooks β†’ Add webhook
  2. Enter payload URL (HTTPS required in production)
  3. Set content type to application/json
  4. Generate and save secret token
  5. Select events to trigger

Payload URL examples:

  • Development: https://abc123.ngrok.io/webhook
  • Production: https://api.example.com/webhook

πŸ”‘ Setup - Secret Generation

Generate a secure webhook secret.

# Linux/Mac
openssl rand -hex 32

# Or use Node.js
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

# Or use Python
python3 -c "import secrets; print(secrets.token_hex(32))"

βœ”οΈ Setup Checklist

Complete setup checklist for production webhooks.

GitHub Settings:

  • Go to Settings β†’ Webhooks β†’ Add webhook
  • Enter payload URL (HTTPS required in production)
  • Set content type to application/json
  • Generate and save secret token
  • Select events to trigger

Code:

  • Implement signature verification
  • Add event type handling
  • Configure deployment script path
  • Set up error logging

Security:

  • Use HTTPS in production
  • Store secret in environment variable
  • Add rate limiting
  • Set proper file permissions on deploy script
  • Add IP allowlist (optional)

πŸ’‘ Production Tips

Best practices for production webhook deployment.

Run as Service:

# systemd (Linux)
sudo systemctl enable your-webhook.service

# PM2 (Node.js)
pm2 start app.js --name webhook
pm2 startup
pm2 save

Logging:

# Redirect to log file
exec >> /var/log/webhook.log 2>&1

Monitor:

  • Check GitHub webhook delivery tab for failures
  • Set up alerts for 4xx/5xx responses
  • Log all webhook payloads for debugging

🌍 GitHub IP Ranges

Optionally restrict webhooks to GitHub IPs.

Get current GitHub IP ranges:

curl https://api.github.com/meta | jq .hooks

Nginx allowlist:

location /webhook {
    allow 192.30.252.0/22;
    allow 185.199.108.0/22;
    allow 140.82.112.0/20;
    deny all;

    proxy_pass http://localhost:3000;
}

🚨 Troubleshooting - Failed Deliveries

Debug failed webhook deliveries.

Check GitHub:

  1. Go to Settings β†’ Webhooks
  2. Click on webhook URL
  3. View β€œRecent Deliveries”
  4. Check response code and body

Common Issues:

  • Server not reachable (DNS, firewall)
  • Invalid SSL certificate
  • Signature verification failed
  • Server returning 500 error
  • Timeout (GitHub waits 10 seconds)

❌ Troubleshooting - Signature Mismatch

Fix signature verification errors.

Checklist:

  • Using correct secret
  • Reading raw request body
  • Using SHA-256 (not SHA-1)
  • Comparing with X-Hub-Signature-256 header
  • Using constant-time comparison
  • Not double-parsing JSON

Debug tip:

# Log received signature and computed hash
echo "Received: $signature"
echo "Expected: $computed_hash"

πŸ”„ Webhook Retries

GitHub automatically retries failed webhooks.

Retry behavior:

  • GitHub retries up to 3 times
  • Exponential backoff between retries
  • Stops after 3 consecutive failures

Best practices:

  • Return 2xx status code quickly
  • Process heavy work asynchronously
  • Implement idempotency (handle duplicate events)

⏱️ Rate Limits

Webhook rate limits and quotas.

GitHub limits:

  • Max 1000 webhook deliveries per hour per repository
  • 10 second timeout per request
  • 5 MB max payload size

Your server:

  • Implement rate limiting on webhook endpoint
  • Queue webhooks for processing
  • Don’t block on long-running tasks