Urgent.News

What's breaking now, across thousands of outlets.

Tech

Why your webhook signature check fails (and the bugs that pass it)

In July I wrote about why I built verihook : every provider signs webhooks differently, and I was tired of maintaining five slightly different HMAC functions. Since then verihook has grown to 40+ providers, adapters for ten frameworks, testing helpers and a docs site . Supporting that many providers taught me where webhook verification actually goes wrong. It's rarely the HMAC. It's everything…

In July, the author built verihook due to the diverse way providers sign webhooks, which led to the creation of five distinct HMAC functions that needed continuous maintenance. Over time, verihook grew to support 40+ providers, ten frameworks, testing helpers, and a documentation site. Despite being primarily focused on the HMAC, the author discovered that many verification issues stem from other aspects such as the body, secret, URL, retries, and tests.

The primary mistakes the author observed in webhook verification include:

1. The body parser modifying the signature: Providers sign the exact bytes sent. However, functions like JSON.stringify(JSON.parse(body)) can alter whitespace, escape characters, and number formatting. To avoid this, use raw body parsers such as express.raw(), await request.text(), Fastify's rawBody, or NestJS's rawBody: true. verihook can detect such issues, as it identifies when the body size doesn't match the content-length, which usually indicates the body has been parsed and re-serialized.

2. Using the wrong secret: Common errors include using an API key instead of the endpoint's signing secret or using the test-mode secret in production. Slack bot tokens, trailing newlines, or quotes from the .env file can also result in signature mismatches. verihook recognizes these mistakes by analyzing the shape of the secret and providing a hint indicating the specific error.

3. Proxy altering the URL: Services like Twilio, Square, and HubSpot sign the public URL they called. When the server is behind an ngrok, load balancer, or API Gateway, it receives a different URL (e.g., http://10.0.0.5:3000/... instead of https://api.example.com/...). To resolve this, rebuild the URL from x-forwarded-proto and x-forwarded-host or explicitly pass the public URL during verification.

4. Duplicate webhook processing: Providers typically retry at least once if there's a timeout, and a valid signature accepts all copies. To prevent this, implement deduplication using a key that includes data covered by the signature (for example, a signed ID header, an ID inside the signed body, or a hash of the body). In the case of GitHub, using x-github-delivery as a dedupe key can lead to an attacker replaying a captured webhook and bypassing the dedupe store. verihook only keys on data covered by the signature, such as a signed ID header or a hash of the body.

5. Relying on tests that test themselves: A classic example is when the verihook Paddle verifier uses the h= header in the Paddle-Signature header, while the test signer writes h=. Every test pass, but real Paddle webhooks are rejected as they send h1=. To avoid this, use known-good vectors from the provider's documentation, such as a payload, secret, and signature that you didn't compute yourself.

Additionally, perform conformance tests against official SDKs, and leverage verihook's CI, which signs with official Stripe, Octokit, Svix, and Twilio SDKs and verifies with verihook, as well as the reverse. You can find examples in the verihook documentation, which includes a page for each provider detailing where to locate the secret in each dashboard.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

Making My Platform API Reconcile Application Updates

In the previous post, I built the first real behavior for Platform Lab. A developer could create: apiVersion : platform.shubforge.dev/v1alpha1 kind : Application metadata : name : greeting-service…

  • Platform API reconciles application updates by modifying existing resources
  • kubectl patch command updates Application specifications like image, replicas, and ports
  • Controller recalculates desired state and reconciles with actual resources

GoodFirst : I built my friend a way into open source.

This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend What I Built My friend Shivin wanted to get into open source this October. He could code.

  • Shivin created GoodFirst to help friends enter open source.
  • GoodFirst identifies beginner issues and provides CI help.
  • Tool runs on laptop with minimal requirements, no costs.

More from Saturday 3 October →