fix(security): add webhook signature verification for Webflow, HubSpot, and Airtable#4612
fix(security): add webhook signature verification for Webflow, HubSpot, and Airtable#4612waleedlatif1 wants to merge 5 commits into
Conversation
…t, and Airtable All three handlers accepted any POST to the webhook path without verifying the provider's signature, enabling spoofed events to trigger arbitrary workflow executions. Webflow: - Capture `secretToken` from the subscription creation response and persist it as `webhookSecret` in providerConfigUpdates (previously discarded) - Add `verifyAuth` using HMAC-SHA256(rawBody, webhookSecret), comparing against `X-Webflow-Signature` HubSpot: - Add `verifyAuth` using SHA256(clientSecret + rawBody) → hex, comparing against `X-HubSpot-Signature` (v1 scheme; `clientSecret` was already collected in providerConfig but never used for verification) Airtable: - Capture `macSecretBase64` from the subscription creation response and persist it as `webhookSecret` (previously discarded) - Add `verifyAuth` using HMAC-SHA256(rawBody, base64decode(webhookSecret)) → base64, comparing against `X-Airtable-Content-Mac: hmac-sha256=<hash>` All implementations use timing-safe comparison via `safeCompare` and return null on success / 401 on failure, matching the existing provider pattern.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Airtable and Webflow now persist provider-issued signing secrets during subscription creation ( Reviewed by Cursor Bugbot for commit c7cd4ae. Configure here. |
Greptile SummaryThis PR adds cryptographic webhook signature verification to three previously unprotected providers — Webflow, HubSpot, and Airtable — following the existing
Confidence Score: 5/5All three verification paths are correctly implemented against each provider's documented algorithm; no logic errors or missing guards found. The HMAC algorithms, key decoding, timing-safe comparisons, replay-protection windows, and isNaN guards are all correct. Backward compatibility (skip when secret absent + warn) is handled consistently across all three providers. The Airtable MAC format and pyAirtable reference implementation confirm hmacSha256Hex is the right function to use. No files require special attention. Important Files Changed
Reviews (5): Last reviewed commit: "fix(security): guard NaN timestamp befor..." | Re-trigger Greptile |
…irtable
- Webflow: sign `${timestamp}:${rawBody}` per official docs (was rawBody only),
capture `secretKey` not `secretToken` from create response, add 5-minute
replay protection via X-Webflow-Timestamp
- Airtable: use hmacSha256Hex for hmac-sha256=<hex> format (was Base64)
…t absent - HubSpot: dispatch on X-HubSpot-Signature-Version (v1/v2/v3); v1 keeps existing SHA-256(secret+body) logic, v2 adds httpMethod+url to hash, v3 uses HMAC-SHA256 with timestamp replay protection (5 min window) - Webflow/Airtable/HubSpot: log warn when webhookSecret absent so operators can identify webhooks that still need re-registration
|
@greptile |
|
@cursor review |
- Detect v3 by presence of X-HubSpot-Signature-v3 header (HubSpot does not send X-HubSpot-Signature-Version for v3 requests) - Use X-HubSpot-Request-Timestamp for replay protection (not the non-existent X-HubSpot-Signature-Timestamp header) - Simplify v1/v2 path: both use X-HubSpot-Signature, read once before the version branch
Number(timestamp) returns NaN for non-numeric strings; Math.abs(Date.now() - NaN) is NaN which is never > FIVE_MINUTES_MS, silently bypassing replay protection. Add isNaN guard in both Webflow and HubSpot v3 timestamp checks.
|
@greptile |
|
@cursor review |
|
@greptile |
|
@cursor review |
|
@greptile |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit c7cd4ae. Configure here.
Summary
Three webhook handlers were accepting any POST to their endpoint without verifying the provider's cryptographic signature, enabling spoofed events to trigger arbitrary workflow executions.
secretTokenfrom subscription creation response (previously discarded) and verifyX-Webflow-Signatureusing HMAC-SHA256X-HubSpot-Signatureusing SHA256(clientSecret + rawBody) — theclientSecretwas already collected inproviderConfigbut never used for verificationmacSecretBase64from subscription creation response (previously discarded) and verifyX-Airtable-Content-Macusing HMAC-SHA256 with base64-decoded keyAll three use timing-safe comparison via
safeCompareand follow the existingverifyAuthprovider pattern. If the secret is absent (e.g. a pre-existing webhook subscription that predates this fix), verification is skipped (return null) to avoid breaking existing integrations.Test plan
X-HubSpot-Signature— should receive 401macSecretBase64is persisted after trigger creationX-Airtable-Content-Mac— should receive 401