CommunityCodierung & Entwicklunggithub.com

atokim4/stripe-webhook-security

Überprüft und repariert Stripe-Webhook-Endpunkte. Scannt nach Handlern, die auf Stripe-Ereignisse reagieren, ohne `constructEvent`-Signaturprüfung, und nach Signaturen, die gegen einen geparsten Body (`req.json()`, `JSON.stringify`, `express.json()`, eine pages/api-Route mit Standard-Body-Parser) geprüft werden. Anschließend werden die Schritte zur Rohdaten-, Idempotenz-, Wiedergabe- und Secret-Behandlung durchlaufen. Verwenden Sie dies, wenn der Benutzer einen Stripe-Webhook schreibt oder überprüft, fragt "Ist mein Stripe-Webhook sicher?", die Fehlermeldung "Keine Signaturen gefunden, die der erwarteten Signatur entsprechen" erhält, oder kurz vor dem Start einer App steht, die Zahlungen akzeptiert.

Was ist stripe-webhook-security?

Der Skill `atokim4/stripe-webhook-security` führt eine automatisierte Sicherheitsüberprüfung von Stripe-Webhook-Handlern durch. Er verwendet ein lokales Skript (`scripts/preflight.mjs`), das ohne Abhängigkeiten und Netzwerk auskommt und Next.js-Route-Handler, pages/api, Express und Supabase Edge Functions unterstützt. Der Scanner findet zwei kritische Probleme: Erstens Handler, die Stripe-Ereignisse verarbeiten, ohne jemals `constructEvent`/`constructEventAsync` aufzurufen, was die Endpunkte für gefälschte Ereignisse öffnet (Fehlerstufe). Zweitens Handler, die die Signatur gegen einen bereits geparsten Body prüfen, was dazu führt, dass echte Ereignisse mit einem 400-Fehler abgewiesen werden (Warnstufe). Nach dem Scan leitet der Skill Sie durch eine manuelle Überprüfung von Aspekten, die der Code-Scanner nicht erfassen kann: Geheimnisverwaltung (kein öffentliches Secret), Replay-Schutz, Idempotenz (Ereignisse können doppelt zugestellt werden), Ereignisreihenfolge, Vertrauenskontext (nur Daten aus dem verifizierten Ereignis verwenden), schnelle 2xx-Antworten und Beschränkung der Ereignisliste auf die tatsächlich verarbeiteten Ereignisse. Das Ergebnis ist ein detaillierter Bericht, der auch eine erneute Überprüfung nach Korrekturen und die Möglichkeit enthält, Fehlalarme gezielt auszuschließen. Dieser Skill ist besonders wertvoll kurz vor dem Start einer zahlungsverarbeitenden Anwendung oder bei der Fehlersuche an Stripe-Webhooks.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/atokim4/vibe-preflight/tree/HEAD/skills/stripe-webhook-security

Installed? Explore more Codierung & Entwicklung skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Stripe-Webhook-Sicherheit

Dieser Skill führt den Stripe-Teil des vibe-preflight-Scanners aus (scripts/preflight.mjs neben dieser Datei, Node 20+, keine Abhängigkeiten, kein Netzwerk). Er findet Webhook-Handler in Next.js-Route-Handlern, pages/api, Express und Supabase Edge Functions und überprüft zwei Dinge im Code. Der Rest dieser Seite ist eine Überprüfung, die Sie durch Lesen des Handlers durchführen, da ein Pattern-Scan es nicht beweisen kann.

1. Scan ausführen

Aus dem Projektstammverzeichnis:

node ${CLAUDE_SKILL_DIR}/scripts/preflight.mjs . --only stripe --fail-on warning --format json

Claude Code füllt ${CLAUDE_SKILL_DIR} aus. Andere Agenten: Verwenden Sie den Ordner dieses Skills, z. B. .agents/skills/stripe-webhook-security oder .claude/skills/stripe-webhook-security.

RegelStufeBedeutung
stripe-webhook-unverifiedFehlerDer Handler reagiert auf Stripe-Ereignisse und ruft nie constructEvent / constructEventAsync auf. Jeder, der die URL findet, kann ein gefälschtes checkout.session.completed POSTen.
stripe-webhook-parsed-bodyWarnungDie Signatur wird geprüft, aber gegen einen bereits geparsten Body. Stripe signiert die exakten Bytes, die es gesendet hat, daher schlagen echte Ereignisse mit 400 fehl und jemand löscht irgendwann die Überprüfung.

--only stripe findet einen Handler anhand von Stripe-Ereignisnamen, einem Lesen des stripe-signature-Headers oder eines Webhook- Pfads in einer Datei, die Stripe erwähnt. Wenn der Scan 0 Fehler meldet, der Benutzer aber weiß, dass er einen Webhook hat, suchen Sie selbst nach dem Handler und führen Sie trotzdem die untenstehende Überprüfung durch.

2. Verifizierung reparieren

Route-Handler (Next.js App Router, Remix, Hono und andere fetch-ähnliche Handler):

export async function POST(request: Request) {
  const body = await request.text(); // roher Body, niemals request.json()
  const signature = request.headers.get("stripe-signature");
  if (!signature) return new Response("Fehlende Signatur", { status: 400 });
  let event: Stripe.Event;
  try {
    event = stripe.webhooks.constructEvent(body, signature, process.env.STRIPE_WEBHOOK_SECRET!);
  } catch {
    return new Response("Ungültige Signatur", { status: 400 });
  }
  // Ereignis verarbeiten
  return Response.json({ received: true });
}

Express: Registrieren Sie die Webhook-Route mit express.raw({ type: "application/json" }) vor app.use(express.json()) und übergeben Sie req.body (dann ein Buffer) an constructEvent.

Next.js pages/api: export const config = { api: { bodyParser: false } }; und lesen Sie die rohe Anfrage in einen Buffer, bevor Sie verifizieren.

Supabase Edge Functions und andere Deno-/Edge-Laufzeiten: await stripe.webhooks.constructEventAsync(body, signature, secret, undefined, Stripe.createSubtleCryptoProvider()).

3. Überprüfen Sie den Rest, indem Sie den Handler lesen

Der Scanner überprüft diese Punkte nicht. Sehen Sie sich den Code an und teilen Sie dem Benutzer mit, was Sie zu jedem Punkt gefunden haben.

  • Secret. STRIPE_WEBHOOK_SECRET (whsec_...) kommt aus der Server-Umgebung, niemals aus einer NEXT_PUBLIC_ / VITE_-Variable oder dem Quellcode. Der Testmodus und der Live-Modus haben unterschiedliche Secrets, ebenso wie jeder Endpunkt und die stripe listen-CLI.
  • Wiedergabe. constructEvent lehnt eine Signatur ab, die älter als seine Toleranz ist (300 Sekunden Standardwert). Lassen Sie das Toleranzargument weg oder halten Sie es klein. Fangen Sie niemals den Fehler ab und machen Sie weiter.
  • Idempotenz. Stripe kann dasselbe Ereignis mehr als einmal zustellen. Machen Sie entweder den Schreibvorgang von Natur aus wiederholbar (ein Upsert, der nach der Stripe-ID schlüsselt, setzen Sie einen Status, anstatt Guthaben hinzuzufügen) oder speichern Sie event.id in einer Tabelle mit einer eindeutigen Einschränkung und überspringen Sie IDs, die Sie bereits gesehen haben. Achten Sie genau auf alles, was hinzufügt: Guthaben, Kontostand, Lagerbestand.
  • Reihenfolge. Ereignisse können in falscher Reihenfolge eintreffen. Rufen Sie für Abonnements das aktuelle Objekt von der API ab (stripe.subscriptions.retrieve) oder vergleichen Sie Zeitstempel, anstatt der Reihenfolge der Ereignisse zu vertrauen.
  • Vertrauen. Nehmen Sie Benutzer und Plan aus dem verifizierten Ereignis (client_reference_id, metadata, die Kunden-ID, die Sie beim Checkout gespeichert haben), niemals aus einem Query-String oder einer zweiten nicht signierten Anfrage. Der Weiterleitung auf die Erfolgsseite beweist nichts: Gewähren Sie Zugriff über den Webhook.
  • Antwort. Geben Sie schnell 2xx zurück, sobald das Ereignis gespeichert oder verarbeitet ist. Langsame Arbeit geht an eine Warteschlange. Geben Sie 400 nur für eine ungültige Signatur zurück, damit Stripe-Wiederholungsversuche sinnvoll bleiben.
  • Ereignisliste. Abonnieren Sie den Endpunkt nur für die Ereignisse, die der Code verarbeitet, und ignorieren Sie andere Typen ohne Fehler.

4. Bericht

Listen Sie die Scanner-Ergebnisse auf, dann eine Zeile pro Überprüfungspunkt: in Ordnung, behoben oder eine Frage an den Benutzer (z. B. "Guthaben werden bei jeder Zustellung hinzugefügt: Soll ein wiederholtes Ereignis sie erneut hinzufügen?"). Führen Sie den Scan nach der Korrektur erneut aus und zeigen Sie seine letzte Zeile. Um real zu testen, schlagen Sie stripe listen --forward-to localhost:3000/api/webhooks und stripe trigger checkout.session.completed mit der Stripe CLI vor.

Ein bestätigter Fehlalarm kann mit // vibe-preflight-ignore <Regel-ID> in der Zeile oder der Zeile darüber mit dem Grund im Kommentar unterdrückt werden.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Verwandte Skills