---
created: 2026-03-12
source: Growth-Engine
tags: [agent-archive, growth-engine]
---

# Webhook Security Implementation

## Overview
This document describes the webhook signature validation implementation for the Growth Engine API. Webhook endpoints without signature validation can be spoofed by attackers, allowing them to inject fake data or trigger unauthorized actions.

## Critical Security Issue (Audit Item C8)
The audit identified that `/api/voice` and `/api/vapi` webhook routes were missing signature validation, making them vulnerable to spoofing attacks.

## Implemented Solution

### 1. Twilio Webhook Validation
**Location**: `src/middleware/webhookValidation.js`
**Middleware**: `validateTwilioWebhookMiddleware`

**How it works**:
- Validates `X-Twilio-Signature` header using Twilio's official validation method
- Uses `TWILIO_AUTH_TOKEN` from environment variables
- Applies to all POST webhook endpoints under `/api/voice`:
  - `/twiml` (POST only, GET is for testing)
  - `/inbound`
  - `/inbound-status`
  - `/voicemail`
  - `/voicemail-complete`
  - `/call-status`
  - `/recording-status`
  - `/transcribe-recording`
  - `/backfill-transcripts`

**Note**: SMS webhooks at `/api/webhooks/twilio/inbound` already had validation (see `src/routes/webhooks.js` line 27-34).

### 2. VAPI Webhook Validation
**Location**: `src/middleware/webhookValidation.js`
**Middleware**: `validateVapiWebhookMiddleware`

**How it works**:
- Validates VAPI webhook signatures using HMAC-SHA256
- Uses `VAPI_PUBLIC_KEY` from environment variables
- Applies only to `/api/vapi/webhook` endpoint
- Supports multiple signature patterns (common webhook implementations)
- Includes replay attack protection via timestamp validation

**Note**: VAPI's actual webhook signature format needs verification. The current implementation supports common patterns but may need adjustment once official documentation is reviewed.

### 3. Raw Body Middleware
**Location**: `src/middleware/webhookValidation.js`
**Middleware**: `rawBodyMiddleware`

**Purpose**: Preserves raw request body for signature validation (Express.json() parses the body, making it unsuitable for signature calculation).

## Environment Variables Required

### Twilio
```
TWILIO_ACCOUNT_SID=your_account_sid
TWILIO_AUTH_TOKEN=your_auth_token
TWILIO_PHONE_NUMBER=+61468087171
TWILIO_API_KEY_SID=your_api_key_sid
TWILIO_API_KEY_SECRET=your_api_key_secret
TWILIO_TWIML_APP_SID=your_twiml_app_sid
```

### VAPI
```
VAPI_API_KEY=your_vapi_api_key
VAPI_PUBLIC_KEY=your_vapi_public_key  # For webhook signature validation
VAPI_ASSISTANT_ID=your_assistant_id
VAPI_PHONE_NUMBER_ID=your_phone_number_id
```

### Server Configuration
```
APP_URL=https://rateright-growth-production.up.railway.app
INTERNAL_JOB_KEY=secure_random_key
```

### Development Flags (Optional)
```
SKIP_WEBHOOK_VALIDATION=false  # Set to true in development to skip validation
REQUIRE_VAPI_SIGNATURE=true    # Set to false if VAPI doesn't sign webhooks
```

## Implementation Details

### File Changes

1. **New File**: `src/middleware/webhookValidation.js`
   - Contains all webhook validation logic
   - Exports middleware functions and validation utilities

2. **Modified**: `src/index.js`
   - Added `rawBodyMiddleware` before `express.json()` for webhook routes
   - Added validation middleware to `/api/voice` and `/api/vapi` routes
   - Updated CORS headers to allow webhook signature headers

3. **Modified**: `.env` and `.env.example`
   - Added required environment variables
   - Added webhook security configuration options

### Security Considerations

1. **Replay Attack Protection**: VAPI validation includes timestamp checking (5-minute window)
2. **Constant-Time Comparison**: Uses `crypto.timingSafeEqual()` to prevent timing attacks
3. **Graceful Degradation**: In development, validation can be skipped with `SKIP_WEBHOOK_VALIDATION=true`
4. **Selective Validation**: Only applies to actual webhook endpoints, not all API routes

### Testing

Run the test script to verify implementation:
```bash
node test-webhook-validation.js
```

## Deployment Instructions

1. **Update Environment Variables**:
   - Add actual Twilio credentials to `.env` file
   - Add actual VAPI credentials to `.env` file
   - Set `APP_URL` to your production URL

2. **Verify VAPI Signature Format**:
   - Check VAPI documentation for actual webhook signature format
   - Update `validateVapiWebhookSignature` if needed

3. **Monitor Logs**:
   - Watch for `[Webhook Security]` log messages
   - Investigate any signature validation failures

4. **Test in Production**:
   - Make test calls to verify webhooks still work
   - Check that invalid signatures are rejected (401 response)

## Future Improvements

1. **VAPI Signature Verification**: Confirm actual VAPI webhook signature format
2. **Signature Logging**: Add more detailed logging for debugging
3. **Rate Limiting**: Consider additional rate limiting for webhook endpoints
4. **IP Whitelisting**: Optionally restrict webhooks to known Twilio/VAPI IP ranges

## References

- Twilio Webhook Security: https://www.twilio.com/docs/usage/webhooks/webhooks-security
- VAPI Documentation: https://docs.vapi.ai/ (check for webhook security)
- Express Middleware: https://expressjs.com/en/guide/using-middleware.html
- Node.js Crypto: https://nodejs.org/api/crypto.html