From 11cfda1c3cdb02b16167ca7a6aceb2ecca785159 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2026 10:58:19 +0000 Subject: [PATCH 1/2] Fix insecure base64 webhook signature with HMAC-SHA256 Co-authored-by: Pmaster-dev <293764797+Pmaster-dev@users.noreply.github.com> --- .jules/sentinel.md | 6 ++++++ server/services/WebhookService.ts | 16 +++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 .jules/sentinel.md diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..904a807 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,6 @@ +# Sentinel Security Journal + +## 2026-03-31 - HMAC SHA-256 Webhook Signatures +**Vulnerability:** Base64 pseudo-signature was used for `X-Webhook-Signature` in `WebhookService`, allowing webhook payload forgery and tampering. +**Learning:** Prototype implementations may fall back to Base64 encoding instead of cryptographic HMAC signing. +**Prevention:** Always use HMAC-SHA256 with a secure secret key (`WEBHOOK_SECRET` or `SESSION_SECRET`) for outgoing webhook signature verification. diff --git a/server/services/WebhookService.ts b/server/services/WebhookService.ts index 100cb5b..062aa1f 100644 --- a/server/services/WebhookService.ts +++ b/server/services/WebhookService.ts @@ -1,4 +1,5 @@ import axios from 'axios'; +import crypto from 'crypto'; import { v4 as uuidv4 } from 'uuid'; import { storage } from '../storage'; import { Client as NotionClient } from '@notionhq/client'; @@ -285,14 +286,19 @@ export class WebhookService { } /** - * Generate a signature for webhook payload verification + * Generate HMAC-SHA256 signature for webhook payload verification + * SECURITY RISK: Base64 encoding allows attackers to easily forge or tamper with webhook payloads. + * FIX: Generate HMAC-SHA256 signature using a secret key and timestamp to ensure payload authenticity and integrity. */ private generateSignature(payload: WebhookPayload): string { - // In a real app, you would use a crypto library to generate HMAC signatures - // For this prototype, we're using a simple approach - const timestamp = new Date().getTime().toString(); + const secret = process.env.WEBHOOK_SECRET || process.env.SESSION_SECRET; + if (!secret) { + throw new Error('WEBHOOK_SECRET or SESSION_SECRET environment variable is required to sign webhook payloads securely.'); + } + const timestamp = Date.now().toString(); const payloadStr = JSON.stringify(payload); - return `${timestamp}.${Buffer.from(payloadStr).toString('base64')}`; + const signature = crypto.createHmac('sha256', secret).update(`${timestamp}.${payloadStr}`).digest('hex'); + return `t=${timestamp},v1=${signature}`; } /** From 4363c0919c28fd00bdfec436bc15a82c878bde35 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2026 11:08:08 +0000 Subject: [PATCH 2/2] Fix insecure base64 webhook signature with HMAC-SHA256 Co-authored-by: Pmaster-dev <293764797+Pmaster-dev@users.noreply.github.com>