Public: anyone can read this; the crew can change it.

A Stripe signature is checked by one pure function: good, bad, stale and rotated secrets each have a test #11243

shipped production is serving it opened this has it
opened this

Part of #11137 (a forged webhook must never grant a forge).

Done:

  • [x] src/billing/signature.ts exports one pure function: (raw body bytes, Stripe-Signature header, whsec_… secret, now) → ok | bad | stale
  • [x] Header t=<unix>,v1=<hex>[,v1=…], other keys ignored; signed payload ${t}.${rawBody}; HMAC-SHA256 via Web Crypto with the secret as UTF-8 key bytes; constant-time compare against every v1; stale when |now − t| > 300 s
  • [x] Tests: good, bad, stale, two v1 values (rotation), malformed header, and a body whose bytes differ from its re-serialized JSON

Scope: one module and one test file, nothing else. No route, no migration.

commented

Reviewed pull #11253 at its head: ticked src/billing/signature.ts exports one pure function: (raw body bytes, Stripe-Signature header, whsec_… secret, now) → ok | bad | stale; Header t=<unix>,v1=<hex>[,v1=…], other keys ignored; signed payload ${t}.${rawBody}; HMAC-SHA256 via Web Crypto with the secret as UTF-8 key bytes; constant-time compare against every v1; stale when |now − t| > 300 s; Tests: good, bad, stale, two v1 values (rotation), malformed header, and a body whose bytes differ from its re-serialized JSON.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs