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
- 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.
- 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.
- 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.
- Enforce TLS everywhere. Webhook URLs must be HTTPS with a valid certificate; Twilio API calls are HTTPS-only. Reject plaintext.
- 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.
- 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.
- 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.
- 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):
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.
1---2name: twilio-security-hardening3description: 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.4---56## When to use78Use 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.910**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`).1112## Method13141. 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.152. 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.163. 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.174. Enforce TLS everywhere. Webhook URLs must be HTTPS with a valid certificate; Twilio API calls are HTTPS-only. Reject plaintext.185. 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.196. 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.207. 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.218. 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).2223## Example2425Validate the `X-Twilio-Signature` on an inbound webhook (Node, Express):2627```js28const twilio = require('twilio');2930app.post('/twilio/sms', express.urlencoded({ extended: false }), (req, res) => {31 const signature = req.header('X-Twilio-Signature');32 // Reconstruct the exact public URL Twilio called (mind proxy/host rewrites)33 const url = `https://${req.headers['x-forwarded-host'] ?? req.headers.host}${req.originalUrl}`;3435 const valid = twilio.validateRequest(36 process.env.TWILIO_AUTH_TOKEN, // signing key = Auth Token37 signature,38 url,39 req.body // POST params, unsorted; validator sorts them40 );4142 if (!valid) return res.status(403).send('Invalid signature');43 // ...handle the message44 res.type('text/xml').send('<Response/>');45});46```4748Twilio's Express integration also ships `webhook()` middleware that runs this validation automatically.4950## Pitfalls5152- **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.53- **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-*`).54- **Reimplementing HMAC-SHA1.** Subtle param-sorting and encoding differences silently break validation. Use the SDK `validateRequest`/`RequestValidator`.55- **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).56- **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.57- **Secrets in logs.** Framework logs and error traces often capture tokens and request bodies. Redact credentials and message content from logs.5859## Output format6061```62# Twilio Hardening Review: <integration>63WEBHOOKS: signature-validation=on method=SDK(validateRequest) url-reconstruction=correct64TLS: https-only=yes cert=valid65CREDENTIALS: scoped-api-keys=yes auth-token-rotation=<cadence> secondary-token=<used?>66NETWORK: ip-allowlist=<on|off> rate-limit=<rule> geo-permissions=<set>67FRAUD: usage-triggers=<spend cap> pumping-alerts=on68SECRETS: manager=<ref> logs-redacted=yes client-side=none69AUDIT: monitor/debugger=on event-streams->SIEM watched=[11200,11205,auth-fail]70GAPS: [...]71```7273## Reference7475- 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.76- Signing key: the Account Auth Token. Twilio supports a secondary Auth Token to rotate the primary without downtime; both validate signatures during the overlap.77- Transport: all Twilio API endpoints and webhook URLs require HTTPS/TLS; webhook URLs must present a valid certificate.78- 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.79- 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.80- 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.