From 115b0827be1ff458acbe9ad8a30fa514b05f9340 Mon Sep 17 00:00:00 2001 From: Rexxy <125175246+Rexxyin@users.noreply.github.com> Date: Thu, 26 Feb 2026 23:44:26 +0530 Subject: [PATCH] Harden signature parsing and verification edge cases --- src/upstash/queue.ts | 1 - src/verifiers/algorithms.ts | 22 +++++++++++++++------- src/verifiers/base.ts | 2 +- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/upstash/queue.ts b/src/upstash/queue.ts index bff1a31..78fd7c9 100644 --- a/src/upstash/queue.ts +++ b/src/upstash/queue.ts @@ -232,7 +232,6 @@ export async function handleProcess( const verification = await receiver.verify({ signature, body: rawBody, - url: request.url, }); if (verification === false) { diff --git a/src/verifiers/algorithms.ts b/src/verifiers/algorithms.ts index bb28a9c..6b85639 100644 --- a/src/verifiers/algorithms.ts +++ b/src/verifiers/algorithms.ts @@ -37,7 +37,7 @@ export abstract class AlgorithmBasedVerifier extends WebhookVerifier { abstract verify(request: Request): Promise; protected parseDelimitedHeader(headerValue: string): Record { - const parts = headerValue.split(/[;,]/); + const parts = headerValue.split(/,(?=\s*[A-Za-z0-9_-]+\s*=)|;/); const values: Record = {}; for (const part of parts) { @@ -111,16 +111,19 @@ export abstract class AlgorithmBasedVerifier extends WebhookVerifier { const timestampHeader = request.headers.get(this.config.timestampHeader); if (!timestampHeader) return null; + let parsed: number; switch (this.config.timestampFormat) { - case "unix": - return parseInt(timestampHeader, 10); case "iso": - return Math.floor(new Date(timestampHeader).getTime() / 1000); + parsed = Math.floor(new Date(timestampHeader).getTime() / 1000); + break; + case "unix": case "custom": - return parseInt(timestampHeader, 10); default: - return parseInt(timestampHeader, 10); + parsed = parseInt(timestampHeader, 10); + break; } + + return Number.isFinite(parsed) ? parsed : null; } protected extractTimestampFromSignature(request: Request): number | null { @@ -133,7 +136,12 @@ export abstract class AlgorithmBasedVerifier extends WebhookVerifier { const sigMap = this.parseDelimitedHeader(headerValue); const timestampKey = this.config.customConfig?.timestampKey || "t"; - return sigMap[timestampKey] ? parseInt(sigMap[timestampKey], 10) : null; + if (!sigMap[timestampKey]) { + return null; + } + + const parsed = parseInt(sigMap[timestampKey], 10); + return Number.isFinite(parsed) ? parsed : null; } protected formatPayload(rawBody: string, request: Request): string { diff --git a/src/verifiers/base.ts b/src/verifiers/base.ts index ba7f81d..ee03644 100644 --- a/src/verifiers/base.ts +++ b/src/verifiers/base.ts @@ -21,7 +21,7 @@ export abstract class WebhookVerifier { } protected safeCompare(a: string, b: string): boolean { - if (a.length !== b.length) { + if (Buffer.byteLength(a, 'utf8') !== Buffer.byteLength(b, 'utf8')) { return false; }