Skip to main content

Overview

Base Audit Bot includes a webhook server that receives GitHub push notifications. When monitored repositories are updated, the bot automatically:
  • Posts tweets about repository updates
  • Detects Solidity file changes
  • Triggers re-audits for smart contract modifications
  • Updates the database with the latest commit information

How Webhooks Work

The webhook server runs on port 5000 (configurable) and exposes two endpoints:
  • /health: Health check endpoint
  • /webhook/github: GitHub webhook receiver (via webhook.py:40)
When a push event occurs, GitHub sends a POST request with:
  • Event payload containing commit information
  • HMAC-SHA256 signature for verification
  • Event type header

Prerequisites

1

Bot deployed and running

The webhook server starts automatically when the bot runs.
# Verify webhook server is running
curl http://localhost:5000/health
Expected response:
{"status": "healthy", "timestamp": "2026-03-03T12:00:00.000000"}
2

Public URL or tunnel

GitHub needs to reach your webhook endpoint. Options:
  • Production: Deploy to a server with a public IP/domain
  • Testing: Use ngrok or similar tunnel service
  • Cloud: Deploy to cloud platform with automatic URLs
3

Webhook secret configured

Set WEBHOOK_SECRET in your .env file:
WEBHOOK_SECRET=your_random_webhook_secret_here
Generate a secure secret:
openssl rand -hex 32

Setting Up Webhooks

Step 1: Expose Your Webhook Endpoint

Use a reverse proxy with SSL:
server {
    listen 443 ssl;
    server_name bot.yourdomain.com;
    
    ssl_certificate /etc/letsencrypt/live/bot.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/bot.yourdomain.com/privkey.pem;
    
    location /webhook/github {
        proxy_pass http://localhost:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Hub-Signature-256 $http_x_hub_signature_256;
        proxy_set_header X-GitHub-Event $http_x_github_event;
    }
}
Your webhook URL: https://bot.yourdomain.com/webhook/github

Step 2: Configure GitHub Webhook

1

Navigate to repository settings

Go to your GitHub repository:
https://github.com/username/repository/settings/hooks
2

Add webhook

Click “Add webhook”Fill in the configuration:Payload URL
https://bot.yourdomain.com/webhook/github
Content type
application/json
Secret
[Same value as WEBHOOK_SECRET in .env]
The secret must exactly match WEBHOOK_SECRET in your bot’s .env file. The bot uses HMAC-SHA256 to verify signatures (via webhook.py:49).
3

Select events

Choose which events to receive:
If you want more control, select individual events:
  • Pushes - Repository updates
  • Pull requests - (Future support)
  • Releases - (Future support)
4

Activate webhook

  • Ensure “Active” is checked
  • Click “Add webhook”
GitHub will send a ping event to test the connection.

Step 3: Verify Webhook

1

Check delivery status

In GitHub webhook settings, click on the webhook you just created.Go to “Recent Deliveries” tab.You should see a ping event with:
  • ✅ Green checkmark
  • HTTP 200 response
  • Response body: {"message": "pong"}
2

Check bot logs

# Docker
docker-compose logs -f | grep webhook

# Python
tail -f logs/bot.log | grep webhook
Expected output:
INFO - Received GitHub webhook: ping
INFO - Received ping event
3

Test with a real push

Make a commit and push to the repository:
echo "# Test" >> README.md
git add README.md
git commit -m "Test webhook"
git push
Check bot logs:
INFO - Received GitHub webhook: push
INFO - Push to username/repository: Test webhook

Webhook Events

The bot handles two types of events:

Ping Event

Sent by GitHub to verify webhook configuration (via webhook.py:92). Bot response: Returns {"message": "pong"} with HTTP 200.

Push Event

Sent when commits are pushed to the repository (via webhook.py:88). Bot actions:
  1. Extracts repository and commit information
  2. Checks if any Solidity files (.sol) were modified (via webhook.py:120)
  3. Calls on_push callback to tweet about the update (via webhook.py:148)
  4. If Solidity files changed, calls on_solidity_change to trigger re-audit (via webhook.py:155)
  5. Updates database with latest commit SHA (via webhook.py:228)
Event data structure:
{
    "repo_name": "username/repository",
    "repo_url": "https://github.com/username/repository",
    "ref": "refs/heads/main",
    "commit_sha": "abc123d",
    "commit_message": "Fix reentrancy vulnerability",
    "commit_url": "https://github.com/username/repository/commit/abc123d",
    "author": "John Doe",
    "solidity_changed": true,
    "modified_files": ["contracts/Token.sol", "README.md"]
}
```python

## Security

### Signature Verification

The bot verifies all webhook requests using HMAC-SHA256 (via `webhook.py:49`):

```python
def _verify_signature(self, payload: bytes, signature: str) -> bool:
    """Verify GitHub webhook signature."""
    if not signature.startswith("sha256="):
        return False
    
    expected_signature = "sha256=" + hmac.new(
        self.webhook_secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    
    return hmac.compare_digest(signature, expected_signature)
```python

<Warning>
  **Requests with invalid signatures are rejected with HTTP 401** (via `webhook.py:72`).
  
  This prevents:
  - Unauthorized webhook triggers
  - Malicious payload injection
  - Replay attacks
</Warning>

### Best Practices

<AccordionGroup>
  <Accordion title="Use strong webhook secrets">
    Generate cryptographically secure secrets (minimum 32 characters):

    - Use `openssl rand -hex 32` on Linux/Mac
    - Use `python -c "import secrets; print(secrets.token_hex(32))"` in Python
  </Accordion>
  
  <Accordion title="Enable HTTPS">
    Always use HTTPS for webhook endpoints in production:
    - Prevents man-in-the-middle attacks
    - Protects webhook secret in transit
    - Required by many GitHub organization policies
    
    <Tip>
      Get free SSL certificates from [Let's Encrypt](https://letsencrypt.org/)
    </Tip>
  </Accordion>
  
  <Accordion title="Restrict to GitHub IPs">
    Optionally restrict webhook endpoint to GitHub's IP ranges for additional security.

    <Note>
      GitHub's IP ranges: [https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-githubs-ip-addresses](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-githubs-ip-addresses)
    </Note>
  </Accordion>
  
  <Accordion title="Monitor webhook logs">
    Set up alerts for:
    - Repeated signature verification failures
    - Unusual event frequencies
    - Webhook errors
    - Database anomalies or corruption
  </Accordion>
</AccordionGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="GitHub shows delivery failure">
    **Symptoms**: Red X in Recent Deliveries
    
    **Common causes**:
    1. **Endpoint not accessible**
       - Check firewall rules
       - Verify bot is running
       - Test with: `curl http://your-url/webhook/github`
    
    2. **SSL/TLS issues**
       - Verify certificate is valid
       - Check for self-signed certificate errors
    
    3. **Timeout**
       - Bot taking too long to respond
       - Check bot logs for errors
       - Increase GitHub timeout if needed
  </Accordion>
  
  <Accordion title="Signature verification failing">
    **Symptoms**: Logs show "Invalid webhook signature"
    
    **Causes**:
    1. **Secret mismatch**
       - Verify `WEBHOOK_SECRET` matches GitHub configuration
       - Check for extra whitespace or newlines
    
    2. **Proxy modifying payload**
       - Ensure reverse proxy doesn't alter request body
       - Check `X-Hub-Signature-256` header is forwarded
    
    **Debug**:
    - Check secret in container: `docker-compose exec audit-bot env | grep WEBHOOK_SECRET`
    - Test signature locally: `echo -n '{"test":true}' | openssl dgst -sha256 -hmac "your_secret"`
  </Accordion>
  
  <Accordion title="Events not triggering actions">
    **Symptoms**: Webhook received but no tweets/audits
    
    **Check**:
    1. **Bot logs for errors**
       - Run: `docker-compose logs -f | grep -i error`
    
    2. **Event type**
       - Only `push` events trigger actions
       - Verify event type in GitHub delivery details
    
    3. **Callbacks registered**
       - Check `on_push` and `on_solidity_change` are configured
       - See `webhook.py:206` for callback setup
  </Accordion>
  
  <Accordion title="Health check passing but webhooks failing">
    **Possible causes**:
    1. **Reverse proxy configuration**
       - Ensure `/webhook/github` path is proxied correctly
       - Check headers are forwarded
    
    2. **Request method**
       - Webhooks require POST method
       - Health check uses GET method
    
    **Test**: Send a POST request to your webhook endpoint with GitHub headers to verify it responds correctly.
  </Accordion>
</AccordionGroup>

## Advanced Configuration

### Multiple Repositories

Set up webhooks for multiple repositories using the same bot instance:

1. Configure webhook in each repository (same settings)
2. All repositories send to same URL
3. Bot handles all events through single endpoint

### Custom Event Handling

Modify webhook behavior by editing callback functions in `webhook.py:206`:

```python
def on_push(event_data: dict):
    """Custom push event handler."""
    # Add your custom logic here
    pass

def on_solidity_change(event_data: dict):
    """Custom Solidity change handler."""
    # Add your custom logic here
    pass
```python

### Webhook Testing

Use GitHub's webhook testing features:

1. Go to webhook settings
2. Click **"Recent Deliveries"**
3. Click on any delivery
4. Click **"Redeliver"** to resend the event

<Tip>
  This is useful for debugging without making actual commits.
</Tip>

## Next Steps

- [Configuration Guide](/guides/configuration) - Configure webhook settings
- [Troubleshooting](/guides/troubleshooting) - Common webhook issues
- [Deployment Guide](/guides/deployment) - Production webhook setup

Build docs developers (and LLMs) love