Skip to content

Use constant-time comparison for Shopify and HubSpot webhook signatures #4415

Description

@tiagovilasboas

Two inbound webhook handlers compare the signature/hash with a plain !==, which is not constant-time (CWE-208, timing side channel). The project already uses the correct pattern (crypto.timingSafeEqual) in the Intercom handler, so this is a consistency fix.

Locations (at commit cd857be)

  • apps/web/app/(ee)/api/shopify/integration/webhook/route.ts:38
    if (generatedSignature !== signature) { ... }
  • apps/web/app/(ee)/api/hubspot/webhook/route.ts:39
    if (signature !== expectedHash) { ... }

Reference pattern already in the repo

apps/web/app/(ee)/api/intercom/webhook/verify-webhook-signature.ts (around lines 57-67):

if (providedBuffer.length !== expectedBuffer.length) { throw ...; }
const isSignatureValid = crypto.timingSafeEqual(
  Uint8Array.from(providedBuffer),
  Uint8Array.from(expectedBuffer),
);

Suggested change

Mirror the Intercom approach in the Shopify and HubSpot handlers: compare the raw bytes with a length pre-check and crypto.timingSafeEqual instead of !==.

Severity

Low. Timing attacks against an HMAC comparison over the network are hard to exploit in practice due to jitter; this is defense-in-depth / consistency, not a reported vulnerability. No proof-of-concept.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions