concepts / security

Security

Kite verifies every inbound webhook at the relay edge before it reaches your listener. Unverified or tampered payloads are rejected. Your local app only sees events that have passed cryptographic signature checks.

Signature verification

Each provider signs its webhook payload with a shared HMAC secret. Kite verifies this signature on receipt using the secret you configured. The raw payload is never forwarded until verification passes.

If verification fails, Kite returns 401 Unauthorized to the provider and logs the attempt. Your listener sees nothing.

Supported providers

ProviderSignature headerAlgorithmReplay guard
StripeStripe-SignatureHMAC-SHA256✓ timestamp
GitHubX-Hub-Signature-256HMAC-SHA256id dedup
SlackX-Slack-SignatureHMAC-SHA256✓ timestamp
LinearLinear-SignatureHMAC-SHA256id dedup
ShopifyX-Shopify-Hmac-Sha256HMAC-SHA256id dedup
TwilioX-Twilio-SignatureHMAC-SHA1id dedup
PagerDutyX-PagerDuty-SignatureHMAC-SHA256✓ timestamp

Replay protection

For providers that include a timestamp in the signed payload (Stripe, Slack, PagerDuty), Kite rejects any event where the timestamp is more than 5 minutes old. This prevents attackers from replaying captured requests.

For providers without timestamp signing (GitHub, Linear, Shopify), Kite deduplicates by CloudEvent id within a 24-hour rolling window. Duplicate events are silently dropped.

Secrets management

Webhook signing secrets are stored encrypted at rest using AES-256-GCM. They are never logged or included in any API response. You can rotate a secret without downtime:

$ kite sources update my-stripe \
  --secret $NEW_STRIPE_WEBHOOK_SECRET

Kite accepts both the old and new secret during a configurable overlap window (default: 10 minutes) so you can update the provider secret without dropping events.

Transport security

All traffic between the provider and the Kite relay uses TLS 1.2+. The WebSocket connection between the relay and the CLI uses TLS with certificate pinning. Events in transit are never stored unencrypted.

Summary:

  • Provider → relay: HTTPS (TLS 1.2+), HMAC verified
  • Relay → CLI: WebSocket over TLS, cert-pinned
  • CLI → local sink: plain HTTP (local loopback only)
  • Secrets at rest: AES-256-GCM

Unverified sources

Custom HTTP sources without a signing secret are still accepted and delivered, but are flagged in the CloudEvent extensions:

{
  "kite-verified": "false",
  "kite-source": "http"
}

Your handler can inspect kite-verified and reject or downgrade untrusted events according to your own policy.

Next: Manifest

Combine sources, sinks, and security config into a single declarative kite.json manifest.