# Twilio Security Hardening

> End-to-end Twilio security hardening — validate inbound webhook signatures, enforce TLS, allowlist and rate-limit, rotate credentials, manage secrets, and audit via Monitor and Event Streams.

- Skill: `matrixx0070/twilio-security-hardening` (Agent Skill)
- Install (CLI): `npx skillmds@latest add matrixx0070/twilio-security-hardening`
- Raw SKILL.md: https://api.skillmd.com/api/skills/matrixx0070/twilio-security-hardening/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: Matrixx0070 (https://skillmd.com/u/matrixx0070)
- Updated: 2026-09-08
- Page: https://skillmd.com/skills/matrixx0070/twilio-security-hardening

---


## When to use

Use this when you are exposing webhook endpoints that Twilio calls (incoming SMS/voice, status callbacks) and need to prove requests are genuinely from Twilio, or when hardening a Twilio integration end-to-end for production. Use it before going live with public callback URLs, during a security review, or after any suspected credential or endpoint abuse.

**Not for:** the mechanics of choosing and scoping the credentials your app uses to call Twilio (see `twilio-security-api-auth`), or HIPAA/BAA obligations for PHI (see `twilio-security-compliance-hipaa`).

## Method

1. Validate the signature on every inbound webhook. Twilio signs each request with your Auth Token and sends the result in the `X-Twilio-Signature` header. Reject any request that fails validation — an unvalidated webhook lets anyone spoof incoming calls, texts, and status updates.
2. Understand what is signed so validation is correct: Twilio builds the signature as an HMAC-SHA1 over the full request URL followed by the POST parameters sorted by name and concatenated (key+value), keyed by your Auth Token, then base64-encoded. Use the SDK's `validateRequest` / `RequestValidator` rather than reimplementing.
3. Handle URL and proxy pitfalls: the signature is computed over the exact URL Twilio called (scheme, host, port, query string). Behind a load balancer or proxy that rewrites host/scheme, reconstruct the original public URL or validation will fail for legitimate requests.
4. Enforce TLS everywhere. Webhook URLs must be HTTPS with a valid certificate; Twilio API calls are HTTPS-only. Reject plaintext.
5. Apply least-privilege credentials (per-app scoped API Keys) and rotate the Auth Token and keys on a schedule and on exposure. Note that rotating the Auth Token changes the signing key, so coordinate webhook validation during rotation.
6. Add network and rate controls: IP-allowlist Twilio's published webhook egress ranges where feasible, rate-limit endpoints, and cap message/call spend with usage triggers to contain a compromised credential or a pumping (toll fraud) attack.
7. Manage secrets properly: keep Auth Token, API secrets, and signing keys in a secret manager, out of source control, logs, and client code; scrub credentials from application logs.
8. Audit continuously: use Twilio Monitor (alerts, event logs, debugger) and Event Streams to ship auth failures, error spikes, and geographic anomalies to your SIEM; alert on 11200/11205 webhook errors and on unusual traffic to premium/high-cost destinations (SMS/international pumping).

## Example

Validate the `X-Twilio-Signature` on an inbound webhook (Node, Express):

```js
const twilio = require('twilio');

app.post('/twilio/sms', express.urlencoded({ extended: false }), (req, res) => {
  const signature = req.header('X-Twilio-Signature');
  // Reconstruct the exact public URL Twilio called (mind proxy/host rewrites)
  const url = `https://${req.headers['x-forwarded-host'] ?? req.headers.host}${req.originalUrl}`;

  const valid = twilio.validateRequest(
    process.env.TWILIO_AUTH_TOKEN, // signing key = Auth Token
    signature,
    url,
    req.body                        // POST params, unsorted; validator sorts them
  );

  if (!valid) return res.status(403).send('Invalid signature');
  // ...handle the message
  res.type('text/xml').send('<Response/>');
});
```

Twilio's Express integration also ships `webhook()` middleware that runs this validation automatically.

## Pitfalls

- **No signature validation.** An unvalidated endpoint accepts spoofed inbound messages and forged status callbacks. Validate `X-Twilio-Signature` on every request and 403 on failure.
- **Validating against the wrong URL.** Behind a proxy, `req.host`/`req.protocol` may be the internal value, so the HMAC input differs from what Twilio signed and valid requests fail. Reconstruct the original public HTTPS URL (honor `X-Forwarded-*`).
- **Reimplementing HMAC-SHA1.** Subtle param-sorting and encoding differences silently break validation. Use the SDK `validateRequest`/`RequestValidator`.
- **Auth Token rotation breaks signing.** The Auth Token is the webhook signing key; rotating it invalidates in-flight signatures. Coordinate rotation and validation (Twilio supports a secondary Auth Token for zero-downtime rotation).
- **No spend/rate limits.** A leaked credential or an open endpoint enables SMS/toll pumping fraud that runs up huge bills. Set usage triggers, rate limits, and geo-permissions on messaging/voice.
- **Secrets in logs.** Framework logs and error traces often capture tokens and request bodies. Redact credentials and message content from logs.

## Output format

```
# Twilio Hardening Review: <integration>
WEBHOOKS: signature-validation=on method=SDK(validateRequest) url-reconstruction=correct
TLS: https-only=yes cert=valid
CREDENTIALS: scoped-api-keys=yes auth-token-rotation=<cadence> secondary-token=<used?>
NETWORK: ip-allowlist=<on|off> rate-limit=<rule> geo-permissions=<set>
FRAUD: usage-triggers=<spend cap> pumping-alerts=on
SECRETS: manager=<ref> logs-redacted=yes client-side=none
AUDIT: monitor/debugger=on event-streams->SIEM watched=[11200,11205,auth-fail]
GAPS: [...]
```

## Reference

- Webhook signature: Twilio sends `X-Twilio-Signature`, an HMAC-SHA1 (base64-encoded) computed over the full request URL plus the POST parameters sorted alphabetically by name and concatenated (name+value), keyed by your Auth Token. For JSON/GET bodies Twilio uses the URL (and appends a `bodySHA256` query param for raw bodies). Validate with the helper library's `RequestValidator` / `validateRequest`, or the `webhook()` framework middleware.
- Signing key: the Account Auth Token. Twilio supports a secondary Auth Token to rotate the primary without downtime; both validate signatures during the overlap.
- Transport: all Twilio API endpoints and webhook URLs require HTTPS/TLS; webhook URLs must present a valid certificate.
- Fraud controls: Usage Triggers and Billing alerts cap spend; Voice/Messaging Geographic Permissions restrict high-risk destinations to blunt international revenue-share (toll/SMS pumping) fraud.
- Observability: Twilio Monitor (Alerts, Events, Debugger) and Event Streams export logs and errors; watch webhook errors 11200 (HTTP retrieval failure) and 11205 (HTTPS connection failure), plus authentication failures and traffic anomalies.
- Least privilege: use per-application scoped API Keys (see `twilio-security-api-auth`) rather than the Auth Token for application access; keep all secrets in a secret manager, off the client, and out of logs.

