Skip to content

Commit f2be6b8

Browse files
author
Codex Microtask Operator
committed
Reject malformed CoinPay webhook timestamps
1 parent 8f46915 commit f2be6b8

2 files changed

Lines changed: 5 additions & 1 deletion

File tree

apps/logicsrc-web/contract/logicsrc-web.contract.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,10 @@ describe("POST /api/webhooks/coinpay", () => {
411411
expect(verifyCoinPayWebhook(payload, `t=${timestamp},v1=${signature}`, secret)).toBe(true);
412412
expect(verifyCoinPayWebhook(payload, `t=${timestamp}, v1=${signature}`, secret)).toBe(true);
413413

414+
const malformedTimestamp = `${timestamp}abc`;
415+
const malformedSignature = createHmac("sha256", secret).update(`${malformedTimestamp}.${payload}`).digest("hex");
416+
expect(verifyCoinPayWebhook(payload, `t=${malformedTimestamp},v1=${malformedSignature}`, secret)).toBe(false);
417+
414418
const response = await coinpayWebhook(
415419
new NextRequest("http://localhost/api/webhooks/coinpay", {
416420
method: "POST",

apps/logicsrc-web/src/lib/coinpay.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export function verifyCoinPayWebhook(
117117
const parts = signatureHeader.split(",").map((part) => part.trim());
118118
const timestamp = parts.find((part) => part.startsWith("t="))?.slice(2);
119119
const signature = parts.find((part) => part.startsWith("v1="))?.slice(3);
120-
if (!timestamp || !signature) {
120+
if (!timestamp || !signature || !/^\d+$/.test(timestamp)) {
121121
return false;
122122
}
123123

0 commit comments

Comments
 (0)