Signature verification

How each source proves its events are genuine, and what happens when a signature does not check out.

Core Available on every plan Updated 25 October 2026

These pages describe ShellOrbit as it runs today. Breaking changes to the HTTP API are announced before they ship, and existing request and response shapes stay supported.

Every source has a secret. The sender uses it to sign each request, or sends it in a header, and ShellOrbit checks it on the original bytes before any rule reads the event. A forged event cannot raise or hide a finding.

Formats

Signature verification: Format, Used by, What is checked
FormatUsed byWhat is checked
GitHubGitHub sourcesX-Hub-Signature-256: HMAC SHA256 of the body
ShellOrbitYour app, and your own systemsShellOrbit-Signature: t=<unix>,v1=<hex>: HMAC SHA256 of the timestamp, a dot, and the body, within five minutes
StripeStripeStripe-Signature, the same scheme as ShellOrbit, within five minutes
ShopifyShopifyX-Shopify-Hmac-Sha256: base64 HMAC SHA256 of the body
PaddlePaddlePaddle-Signature: ts and h1, within five seconds
Standard WebhooksSvix, Clerk, Resend, Dodo Payments, and otherswebhook-id, webhook-timestamp, webhook-signature, or the svix- versions, within five minutes
Header secretAWS EventBridge, Okta, Auth0The header the source page names must carry the source secret

Sign your own events

The ShellOrbit format, in Node.js:

js
import crypto from "node:crypto";

const body = JSON.stringify(event);
const t = Math.floor(Date.now() / 1000);
const v1 = crypto.createHmac("sha256", process.env.SOURCE_SECRET)
  .update(`${t}.${body}`).digest("hex");
// header: ShellOrbit-Signature: t=${t},v1=${v1}

Sign the exact bytes you send. Re-serialising JSON after signing changes them.

When a check fails

The event is kept and marked as failing, so you can see that someone tried, and it is never run through the rules. The source’s events show the result for every request. The usual causes:

  • The secret in the vendor and in ShellOrbit differ. Paste it again, or rotate it on the source and update the vendor.
  • The body was changed after signing, often by a proxy that re-encodes JSON.
  • The clock on your own sender is off by more than five minutes.

Rotate a secret

Rotate it from the source’s page; the new secret is shown once. Update the vendor straight after: requests signed with the old secret fail from then on.

IP allowlisting

On Business, limit a source to a sender’s published address ranges, such as GitHub’s hook addresses. Requests from anywhere else get 403 and are neither stored nor counted.