Overview
Heimdall supports webhooks from:- GitHub (HMAC-SHA256 signature verification)
- GitLab (token-based verification)
- Verifies the signature/token
- Checks if the repository is registered
- Creates a new scan at the pushed commit SHA
- Triggers the full scan pipeline
- Returns a
200 OKresponse with scan details
Setting Up Webhooks
Generate a Webhook Secret
First, generate a secure random secret:.env file:
Configure Your Git Provider
- GitHub
- GitLab
- Go to Repository Settings → Webhooks → Add webhook
- Set Payload URL:
https://heimdall.example.com/webhooks/github - Set Content type:
application/json - Set Secret: Your
WEBHOOK_SECRETvalue - Select Just the push event
- Ensure Active is checked
- Click Add webhook
Signature Verification
All webhook requests are verified before processing.GitHub (HMAC-SHA256)
GitHub signs webhooks with HMAC-SHA256:- GitHub generates:
HMAC-SHA256(secret, payload) - Sends signature in header:
X-Hub-Signature-256: sha256=<hex_digest> - Heimdall recomputes the signature using the payload and
WEBHOOK_SECRET - Signatures are compared in constant-time to prevent timing attacks
GitLab (Token)
GitLab uses simple token-based verification:- GitLab sends the secret token in header:
X-Gitlab-Token: <secret> - Heimdall compares the token to
WEBHOOK_SECRET(exact string match) - Mismatch returns
401 Unauthorized
GitHub’s HMAC approach is more secure as it prevents replay attacks. For GitLab, ensure your
WEBHOOK_SECRET is sufficiently long (at least 40 characters).Supported Events
Push Events
Both GitHub and GitLab push events trigger full scans. GitHub payload (simplified):Ignored Events
Other event types are accepted but ignored:- Pull requests / Merge requests
- Issues
- Comments
- Releases
Webhook Response
Successful Scan Trigger
Status:200 OK
Body:
Repository Not Found
Status:404 Not Found
Body:
Invalid Signature
Status:401 Unauthorized
Body:
WEBHOOK_SECRET matches between Heimdall and your Git provider.
Troubleshooting
Webhook Secret Not Configured
Symptom: Server logs show “WEBHOOK_SECRET is not configured” Solution:Signature Verification Fails
GitHub symptoms:- Webhook delivery shows “401 Unauthorized”
- Heimdall logs: “GitHub webhook signature verification failed”
- Verify the secret in GitHub webhook settings matches
WEBHOOK_SECRET - Check for extra whitespace in
.env - Ensure
Content-Type: application/jsonis set in GitHub
- Webhook test shows “401 Unauthorized”
- Heimdall logs: “GitLab webhook token verification failed”
- Verify the token in GitLab webhook settings matches
WEBHOOK_SECRETexactly - Check for trailing newlines or spaces in the secret
Repository Not Found
Symptom: Webhook delivers but returns404 Not Found
Solutions:
- Verify the repository is added to Heimdall
- Check the
remote_urlin the database matches the webhook payload: - Re-add the repository if URLs don’t match
Webhook Delays
Symptom: Scans start several minutes after push Cause: Background worker polling interval Solutions:- Check
WORKER_POLL_INTERVAL_SECSin.env(default: 5 seconds) - Reduce for faster scan starts:
- For development, disable worker mode for instant inline scans:
Firewall / Network Issues
Symptom: Webhooks never arrive at Heimdall Solutions:- Verify your webhook endpoint is publicly accessible:
- Check firewall rules allow inbound HTTPS
- Verify DNS resolves correctly
- For GitHub, check the IP allowlist: GitHub IP ranges
Security Best Practices
- Always verify signatures: Never disable signature verification
- Use HTTPS: Webhooks should only be sent to HTTPS endpoints in production
- Rotate secrets periodically: Update
WEBHOOK_SECRETand reconfigure webhooks - Limit webhook scope: Only subscribe to push events
- Monitor failed deliveries: Set up alerts for repeated webhook failures
Testing Webhooks Locally
For local development, use a tunnel service like ngrok:API Reference
| Endpoint | Method | Auth | Description |
|---|---|---|---|
/webhooks/github | POST | HMAC-SHA256 | GitHub webhook receiver |
/webhooks/gitlab | POST | Token | GitLab webhook receiver |