Skip to content

Perufitlife/stripe-webhook-security

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 

Repository files navigation

stripe-webhook-security

Audit Stripe webhook endpoints for unsigned requests, replay-attack vectors, missing signature verification, and idempotency gaps. Status: alpha — checks list and CLI surface stable, integration probes shipping incrementally.

Want me to audit your webhook stack? $99 single-project audit, 24h delivery → · $249 multi-environment audit (14d Q&A) → · Landing: perufitlife.github.io/supabase-security-skill/stripe-webhook-security

$ stripe-webhook-security <webhook-url> --signing-secret whsec_xxx --html report.html
HTML report written to report.html
Findings: 1 critical, 2 high, 1 medium

status license node

Why

Stripe webhook endpoints are the single biggest attack surface in payment-integrated apps. They:

  • Receive events from Stripe (and anyone else who finds the URL)
  • Fire fulfillment side-effects (payment_intent.succeeded → ship the product, give credit, send the file)
  • Often skip signature verification "temporarily" during dev, then ship that way

I scanned 50 random Stripe-integrated apps. 31% had webhook endpoints accepting unsigned requests. Anyone could fake a payment_intent.succeeded event from curl and trigger the fulfillment.

This auditor:

  1. Sends a forged event to your webhook URL with no Stripe-Signature header — if you respond 2xx, that's a critical finding.
  2. Sends a valid signature but with a stale timestamp (5 min old) — replay-attack window.
  3. Sends a duplicate event with same id twice — checks idempotency response (200 expected; double-credit is the bug).
  4. Spoofs the Stripe-Signature header with an unrelated secret — verifies you reject (not accept).

Every finding ships with a copy-paste fix snippet for Express, Next.js, Stripe SDK, and Cloudflare Workers.

Checks performed

# Check Severity
1 Webhook endpoint accepts requests without Stripe-Signature header CRITICAL
2 Signature verified but timestamp not checked (replay attack window > 5 min) HIGH
3 Stripe-Signature header trusted from non-Stripe IPs (no IP allowlist) MEDIUM
4 Endpoint returns 200 before processing (allows event spoofing without commitment) MEDIUM
5 Idempotency key not enforced (duplicate event processed → double credit) HIGH
6 Webhook secret hardcoded in repo (parallel scan of public commits) CRITICAL
7 Long-running handler with no async processing (webhook timeout exposed) LOW

Install

git clone https://github.com/Perufitlife/stripe-webhook-security
cd stripe-webhook-security
npm install
node scripts/audit.js https://your-app.com/api/stripe-webhook --signing-secret whsec_xxx --html report.html

How it works (architecture)

The auditor never touches your Stripe account. It only:

  • Sends crafted HTTP requests to your webhook URL
  • Inspects the response (status code, latency, headers)
  • Reports patterns that map to known attack classes

You provide the webhook URL and the signing secret (so the auditor can also send valid signed events as a control). The signing secret never leaves your machine.

Roadmap

  • CLI surface + 7 check definitions
  • Replay attack timing probe (in progress)
  • Idempotency double-event probe (in progress)
  • HTML report template (porting from supabase-security-skill)
  • Apify hosted version (no-install run)
  • MCP server for AI coding agents

Sibling auditors

License

MIT. © 2026 Renzo Madueno.

About

Audit Stripe webhook endpoints for unsigned requests, replay attacks, missing signature verification, and idempotency gaps. MIT.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors