Description
The webhook model stores signing secrets directly in MongoDB without any encryption or hashing (lib/models/webhookModel.js, line 28: secret: data.secret). These secrets are used to generate HMAC signatures for webhook payloads.
When a webhook is listed via GET /api/webhooks, the serialized response includes the secret in plain text.
Impact
If the MongoDB database is compromised (injection, credential leak, backup exposure, insider threat):
- Attacker gains access to all webhook signing secrets
- Can forge webhook events to external systems (fake attendance records, fake achievements)
- Can inject malicious payloads that appear legitimately signed
- Enables replay attacks against webhook consumers
- No way to detect forged events since signatures will be valid
Location
lib/models/webhookModel.js, Lines 21-37
Suggested Fix
- Store only a hash of the webhook secret (HMAC-SHA256 with a server-side pepper)
- Return the secret only once at creation time, never in GET responses
- When verifying signatures, compute the hash from the provided secret and compare against the stored hash
- Consider using a key derivation function (KDF) so the verification secret never needs to be stored in raw form
Description
The webhook model stores signing secrets directly in MongoDB without any encryption or hashing (
lib/models/webhookModel.js, line 28:secret: data.secret). These secrets are used to generate HMAC signatures for webhook payloads.When a webhook is listed via
GET /api/webhooks, the serialized response includes the secret in plain text.Impact
If the MongoDB database is compromised (injection, credential leak, backup exposure, insider threat):
Location
lib/models/webhookModel.js, Lines 21-37Suggested Fix