FixVibe

// code / spotlight

Webhook Signature Verification

If your webhook handler doesn't verify the signature, anyone can forge events.

Kaitnya

Webhook signature verification is one of the most consistently-skipped steps in integration code, and the reason is structural: the integration works fine without it. The webhook arrives, the body parses, the handler runs, the test passes. Verification is the step you only notice when an attacker posts a forged event to your endpoint. Stripe, GitHub, Clerk, Resend, Linear, Slack, Vercel, and every other service worth integrating with sets a signature header โ€” `Stripe-Signature`, `X-Hub-Signature-256`, `svix-id`, etc. โ€” and explicitly tells you to verify before trusting the payload. The instructions are in the documentation. The skipping is in the codebase.

Cara kerjanya

Each provider computes an HMAC over the raw request body (using a secret you configure on their side), serializes the result into a header, and sends both. Your handler is supposed to: read the raw body (not the parsed body โ€” parsing changes whitespace and breaks the HMAC), recompute the HMAC using your shared secret, compare with the header using a timing-safe equality function, then trust the body. Skip the check and you accept any payload from any caller โ€” Stripe's webhook URL is not authenticated by IP, secret token in URL, or any other mechanism; the signature is the only authentication. The mistakes cluster in three shapes: never adding the verification call (the handler trusts everything), parsing the body before verifying (the HMAC fails because the parsed-and-reserialized body has different whitespace), and using non-timing-safe comparison (`===` against the signature is technically right but timing-leaks the secret bit-by-bit).

Varian-variannya

No signature check at all

Handler parses and trusts every incoming POST. Most common shape; trivially exploitable by anyone who knows the URL.

Verify-after-parse

Handler parses body to JSON, then computes HMAC over the JSON.stringify version. Whitespace differs from the original; HMAC fails. Verification 'works' for legit events because both sides round-trip the same way, but is broken for production-grade attackers.

Non-timing-safe comparison

`if (signature === expectedSignature)` instead of `crypto.timingSafeEqual(...)`. Leaks one bit per request through timing analysis. Less common in practice but a genuine vulnerability.

Replay without timestamp check

Even with HMAC verification, accepting old timestamps lets an attacker replay captured events. Stripe's signature includes a timestamp; rejecting events older than 5 minutes defeats replay.

Radius dampak

Forged events. Stripe webhook fakery: an attacker posts a fake `payment_intent.succeeded` event to your `/api/stripe/webhook` endpoint, your handler marks the order as paid, you ship goods you weren't paid for. GitHub webhook fakery: fake `release.published` event triggers your CI to deploy attacker-controlled artifacts. Clerk webhook fakery: fake `user.created` event seeds a malicious user into your database with admin role. The pattern is identical across providers โ€” without signature verification, the webhook endpoint is an unauthenticated mutation API.

// apa yang fixvibe periksa

Apa yang FixVibe periksa

FixVibe repo scans look for high-confidence security patterns and dependency risk in source context. Reports identify the affected area and recommended fix. For check-specific questions about exact detection heuristics, active payload details, or source-code rule patterns, contact support@fixvibe.app.

Pertahanan kokoh

Always verify signatures before parsing or trusting any body field. Use the official SDK helper when available โ€” `stripe.webhooks.constructEvent(rawBody, sig, secret)` for Stripe, GitHub's documented HMAC SHA-256 over rawBody compared with `crypto.timingSafeEqual`, `svix.verify(rawBody, headers)` for Svix-shaped providers (Resend, Clerk, Linear). Critical: read the raw body before parsing โ€” `req.text()` in Next.js, `bodyParser.raw()` in Express, `express.raw({ type: '*/*' })` middleware, or framework-specific raw-body access. Reject requests without signatures, even in test environments; sloppiness in test becomes sloppiness in prod. Validate the timestamp included in the signature (Stripe's tolerance is 5 minutes by default) so old captured events can't be replayed. Store webhook event IDs after processing and refuse re-processing the same ID โ€” handles legitimate retries without enabling deliberate replay. As a final layer, scope the webhook secret per-provider per-environment so a leak is contained.

Intinya

Signature verification is the difference between a webhook endpoint that's part of a trusted integration and one that's a public mutation API. The verification call is one line. Skipping it is the kind of bug you find in a postmortem rather than a code review.

// run it on your own app

Terus rilis sementara FixVibe yang berjaga.

FixVibe menguji permukaan publik app kamu sebagaimana seorang penyerang akan melakukannya โ€” tanpa agent, tanpa instalasi, tanpa kartu. Kami terus meneliti pola kerentanan baru dan mengubahnya jadi check praktis serta perbaikan siap-tempel untuk Cursor, Claude, dan Copilot.

Kode sumber
116
tes yang dijalankan di kategori ini
modules
76
check kode sumber khusus
setiap pemindaian
487+
tes di seluruh kategori
  • Gratis โ€” tanpa kartu kredit, tanpa instalasi, tanpa ping Slack
  • Cukup tempel URL โ€” kami crawl, probe, dan laporkan
  • Temuan berperingkat severity, di-dedupe jadi sinyal saja
  • AI-ready prompts where code applies, plus operator steps for DNS/provider fixes
Jalankan scan gratis โ†’

// latest checks ยท practical fixes ยท ship with confidence

Webhook Signature Verification โ€” Sorotan Kerentanan | FixVibe ยท FixVibe