# curl https://devtools.krishanchawla.com/raw/github-webhook-reference.txt GITHUB WEBHOOKS - REFERENCE Security headers, events, testing, and setup guide for GitHub webhooks Category: Git · Type: cheatsheet Official docs: https://docs.github.com/en/webhooks ──────────────────────────────────────────────────────────── ## 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. | Header | Description | |--------|-------------| | `X-GitHub-Event` | Event type (push, pull_request, etc.) | | `X-Hub-Signature-256` | HMAC SHA-256 signature for verification | | `X-GitHub-Delivery` | Unique delivery ID | | `User-Agent` | Always 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. | Event | Trigger | |-------|---------| | `push` | Code pushed to repository | | `pull_request` | PR opened, closed, or updated | | `issues` | Issue created or modified | | `release` | Release published | | `workflow_run` | GitHub Actions workflow completed | | `create` | Branch or tag created | | `delete` | Branch or tag deleted | | `fork` | Repository forked | | `star` | Repository starred | | `watch` | Repository watched | ## 📦 Event Payloads Example payload structures for common events. ### Push Event ```json { "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 ```json { "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. ```bash # 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 - Signature Verifier Compute a real signature for your secret and payload, and get a ready-to-run curl command — no more hand-copying hex into `YOUR_SIG`. Prefer the CLI? The "Most used" chips above have the same `openssl`/curl commands for copy-paste without JavaScript. ## 📝 Testing - Payload Examples Save test payloads for different events. **push-event.json:** ```json { "ref": "refs/heads/main", "repository": { "name": "test-repo", "full_name": "user/test-repo" }, "pusher": { "name": "testuser" } } ``` Test with file: ```bash 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. ```bash # 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:** ```bash # systemd (Linux) sudo systemctl enable your-webhook.service # PM2 (Node.js) pm2 start app.js --name webhook pm2 startup pm2 save ``` **Logging:** ```bash # 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: ```bash curl https://api.github.com/meta | jq .hooks ``` **Nginx allowlist:** ```nginx 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:** ```bash # 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 ──────────────────────────────────────────────────────────── Full page: https://devtools.krishanchawla.com/devtools/github-webhook-reference More tools: https://devtools.krishanchawla.com