What is a webhook secret?
A webhook secret is the shared key — issued when you register an endpoint — used to compute and verify webhook signatures. Stripe, GitHub, and Shopify all hand you a secret once at endpoint creation with a "copy this now, you won't see it again" warning. Three properties define a good secret: cryptographically random (not derived from a password), at least 32 bytes of entropy, and per-endpoint (each registered URL gets its own). Storage rules: never commit to git, never log it, never put it in URL query strings, never display in admin UI after creation — only show a fingerprint.
When you register a webhook endpoint with Stripe, GitHub, or Shopify, the dashboard hands you a secret — usually displayed once, with a "copy this now, you won't see it again" warning. That secret is the shared key both sides use to compute the HMAC signature on every delivery.
Three properties define a good secret. Random: generated by a cryptographic RNG, not derived from a password or human input. Long: at least 32 bytes (256 bits) of entropy. Stripe, GitHub, and Shopify all issue secrets in this range. Per-endpoint: each registered webhook URL gets its own secret. If you have one endpoint per environment, you have one secret per environment. Sharing secrets across endpoints means a leak in one place compromises everywhere.
Secret storage is where most teams introduce vulnerabilities. The rules:
- Never commit secrets to git. Use .env files, vaults, or secret managers (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault). git log -p is forever; rotation cleans up the live state but not the history.
- Never log the secret. Not in error messages, not in audit trails, not in debug output. A common bug: catching an HMAC mismatch error and logging the request including headers — the signature header isn't the secret, but logging the secret itself by mistake happens.
- Never put the secret in the URL. ?secret=... ends up in access logs, HTTP referer headers, browser history.
- Never display the secret in admin UI after creation. Show it once at creation, then store only a fingerprint (last 4 chars + a hash) for identification.
The secret is the entire authentication boundary for the webhook. If it leaks, anyone can forge valid webhooks until you rotate. Rotation flow: generate the new secret, configure the receiver to accept *both* old and new for a transition window (5-30 minutes), update the source to use the new secret, wait until you stop seeing old-secret signatures, remove the old secret. Most providers support this dual-secret window during rotation; if yours doesn't, schedule rotation during low-traffic time and accept brief verification gaps.
Secret rotation should be routine. Quarterly is a reasonable default; immediately on suspected leak; immediately when an employee with access to secrets leaves. See signing-secret-rotation for the operational pattern.
See Webhook Secret in real traffic
WebhookWhisper captures every webhook with full headers, body, signature, and timing — so concepts like webhook secret stop being abstract and become something you can inspect.
Start Free