From 69be7a9a35416367ce619d5c36fdca0340924f1f Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 16 Sep 2026 10:41:49 +0000 Subject: [PATCH 1/2] security: use environment variable for HMAC secret in webhook signing - Replace hardcoded "idsec_secret_salt" string in webhook signature generation with process.env.IDSEC_HMAC_SECRET with fallback. - Add security explanation comments. - Add unit test for webhook HMAC signature calculation. Co-authored-by: Pmaster-dev <293764797+Pmaster-dev@users.noreply.github.com> --- server/routes.test.ts | 34 ++++++++++++++++++++++++++++++++++ server/routes.ts | 6 ++++-- 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 server/routes.test.ts diff --git a/server/routes.test.ts b/server/routes.test.ts new file mode 100644 index 0000000..a385828 --- /dev/null +++ b/server/routes.test.ts @@ -0,0 +1,34 @@ +import { describe, it, expect, vi } from "vitest"; +import express from "express"; +import crypto from "crypto"; + +// Helper function that mirrors route signing logic +function computeWebhookSignature(data: any, customSecret?: string): string { + const hmacSecret = customSecret || process.env.IDSEC_HMAC_SECRET || "idsec_secret_salt"; + const payloadString = JSON.stringify(data); + return crypto.createHmac("sha256", hmacSecret).update(payloadString).digest("hex"); +} + +describe("Webhook HMAC signature endpoint calculation", () => { + it("should calculate signature using IDSEC_HMAC_SECRET when set", () => { + const data = { event: "webhook.test", id: 1 }; + const secret = "super_secret_env_key"; + + process.env.IDSEC_HMAC_SECRET = secret; + const signature = computeWebhookSignature(data); + const expected = crypto.createHmac("sha256", secret).update(JSON.stringify(data)).digest("hex"); + + expect(signature).toBe(expected); + delete process.env.IDSEC_HMAC_SECRET; + }); + + it("should fallback to default salt when IDSEC_HMAC_SECRET is unset", () => { + delete process.env.IDSEC_HMAC_SECRET; + const data = { event: "webhook.test", id: 1 }; + + const signature = computeWebhookSignature(data); + const expected = crypto.createHmac("sha256", "idsec_secret_salt").update(JSON.stringify(data)).digest("hex"); + + expect(signature).toBe(expected); + }); +}); diff --git a/server/routes.ts b/server/routes.ts index d10cf6b..2876b70 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -2450,10 +2450,12 @@ CSAF: ${baseUrl}/.well-known/csaf/provider-metadata.json return res.status(400).json({ message: "Missing required fields" }); } - // Create webhook payload with cryptographic signature + // SECURITY: Avoid hardcoding cryptographic HMAC secret salts in source code. + // Load secret from environment variable IDSEC_HMAC_SECRET with a fallback for local development. + const hmacSecret = process.env.IDSEC_HMAC_SECRET || "idsec_secret_salt"; const payloadId = uuidv4(); const payloadString = JSON.stringify(data); - const signature = crypto.createHmac("sha256", "idsec_secret_salt").update(payloadString).digest("hex"); + const signature = crypto.createHmac("sha256", hmacSecret).update(payloadString).digest("hex"); const payload = { id: payloadId, From a948b144419b84246fa1e5295e6d15db1998cef1 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 16 Sep 2026 10:45:41 +0000 Subject: [PATCH 2/2] security: use environment variable for HMAC secret in webhook signing - Replace hardcoded "idsec_secret_salt" string in webhook signature generation with process.env.IDSEC_HMAC_SECRET with fallback. - Add security explanation comments. - Add unit test for webhook HMAC signature calculation. Co-authored-by: Pmaster-dev <293764797+Pmaster-dev@users.noreply.github.com> --- server/routes.test.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/server/routes.test.ts b/server/routes.test.ts index a385828..91c6af3 100644 --- a/server/routes.test.ts +++ b/server/routes.test.ts @@ -1,15 +1,14 @@ -import { describe, it, expect, vi } from "vitest"; -import express from "express"; +import { describe, it, expect } from "vitest"; import crypto from "crypto"; -// Helper function that mirrors route signing logic +// Helper function mirroring webhook signature logic in server/routes.ts function computeWebhookSignature(data: any, customSecret?: string): string { const hmacSecret = customSecret || process.env.IDSEC_HMAC_SECRET || "idsec_secret_salt"; const payloadString = JSON.stringify(data); return crypto.createHmac("sha256", hmacSecret).update(payloadString).digest("hex"); } -describe("Webhook HMAC signature endpoint calculation", () => { +describe("Webhook HMAC signature calculation", () => { it("should calculate signature using IDSEC_HMAC_SECRET when set", () => { const data = { event: "webhook.test", id: 1 }; const secret = "super_secret_env_key";