outgoing-webhooks
Installation
SKILL.md
Outgoing Webhooks
Customer-supplied URLs you POST to when something happens. Treat the URL as attacker-controlled. Sign the body. Pin DNS to a public IP. Never let a broken subscriber block the action that triggered the event.
Inbound webhooks (Stripe, GitHub) are the opposite direction — don't use this skill for those.
Philosophy
- SSRF first. Resolve the host, reject private/loopback/link-local, then
http.ipaddr =that address so a TTL=0 DNS rebind can't send you to 169.254.169.254. - HMAC the payload. Show the secret once. Header like
X-Webhook-Signature: sha256=.... - Delivery is a job with a log row. The user-facing action commits, then
perform_later. Failures retry; they don't roll back the event. - Auto-disable after a streak of failures. Don't hammer a dead endpoint forever.
Records
class Webhook < ApplicationRecord # tenanted, or board-scoped in Fizzy
has_secure_token :signing_secret # or "whsec_#{SecureRandom.urlsafe_base64(32)}"
has_many :deliveries, dependent: :destroy