hcengineering/platform · error

Missing signature

Error message

Missing signature

What it means

The handler responds 400 'Missing signature' when the stripe-signature header is absent. Without it constructEvent cannot verify the request, so it is rejected before verification is attempted.

Source

Thrown at services/payment/pod-payment/src/providers/stripe/webhook.ts:51

  webhookSecret: string,
  stripeApiKey: string,
  req: Request,
  res: Response
): Promise<void> {
  try {
    // Body is a Buffer from express.raw() middleware
    const rawBody = req.body as Buffer
    const sig = req.headers['stripe-signature'] as string

    if (!(rawBody instanceof Buffer) || rawBody.length === 0) {
      ctx.error('Invalid webhook body')
      res.status(400).json({ error: 'Invalid body' })
      return
    }

    if (sig === undefined) {
      ctx.error('Missing Stripe signature header')
      res.status(400).json({ error: 'Missing signature' })
      return
    }

    // Create Stripe instance for webhook verification
    const stripe = new Stripe(stripeApiKey, { apiVersion: '2025-02-24.acacia' })

    // Verify webhook signature and parse event
    let event: Stripe.Event
    try {
      event = stripe.webhooks.constructEvent(rawBody, sig, webhookSecret)
    } catch (err: any) {
      ctx.error('Invalid Stripe webhook signature', { err })
      res.status(403).json({ error: 'Invalid signature' })
      return
    }

    // Route to appropriate handler based on event type
    switch (event.type) {

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Only let Stripe (or stripe listen / stripe CLI) call this endpoint; the signature header is added automatically by Stripe
  2. If testing manually, include a valid Stripe-Signature header generated via stripe CLI
  3. Check ingress/proxy header stripping (e.g. nginx underscores_in_headers or WAF rules)
  4. Verify the webhook endpoint URL registered in Stripe matches this route

Example fix

// before
curl -X POST http://host/webhooks/stripe -d '{...}'
// after
stripe listen --forward-to localhost:3000/webhooks/stripe
stripe trigger customer.subscription.created
Defensive patterns

Strategy: validation

Validate before calling

const sig = req.headers['stripe-signature'] as string | undefined
if (sig === undefined) {
  throw new Error('stripe-signature header required; only Stripe should call this endpoint')
}

Type guard

function hasStripeSignature(headers: Record<string, unknown>): headers is Record<string, string> & { 'stripe-signature': string } {
  return typeof headers['stripe-signature'] === 'string'
}

Prevention

When it happens

Trigger: Caller posts directly to the endpoint (curl/health check) without a stripe-signature header; Stripe CLI forwarded to the wrong path; a proxy strips the custom header; event delivered by something other than Stripe.

Common situations: Manual smoke tests hitting the webhook URL; ingress rules or middleware that drop unknown headers; misconfigured Stripe CLI forward target.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/ad6afdbb041e3d37. Report an issue: GitHub.