fix: webhook HMAC — Gitea sends raw hex, not sha256= prefixed

Gitea's X-Gitea-Signature header contains raw hex HMAC-SHA256.
GitHub's X-Hub-Signature-256 uses the sha256= prefix.
verifySignature now normalises both formats to raw hex before
timingSafeEqual comparison, so pushes from Gitea trigger deploys.
This commit is contained in:
Replit Agent
2026-03-20 21:55:04 +00:00
parent fb6b06020e
commit 630a585178

View File

@@ -43,13 +43,17 @@ function log(msg) {
function verifySignature(payload, signature) {
const hmac = crypto.createHmac('sha256', SECRET);
hmac.update(payload);
const expected = 'sha256=' + hmac.digest('hex');
// Both buffers must be the same length for timingSafeEqual
if (Buffer.byteLength(expected) !== Buffer.byteLength(signature)) return false;
const hexDigest = hmac.digest('hex');
// Gitea sends raw hex in X-Gitea-Signature; GitHub/others send sha256=<hex>
// Normalise both sides to raw hex before comparing
const incomingHex = signature.startsWith('sha256=')
? signature.slice(7)
: signature;
if (!incomingHex || Buffer.byteLength(hexDigest) !== Buffer.byteLength(incomingHex)) return false;
try {
return crypto.timingSafeEqual(
Buffer.from(expected, 'utf8'),
Buffer.from(signature, 'utf8')
Buffer.from(hexDigest, 'utf8'),
Buffer.from(incomingHex, 'utf8')
);
} catch (_) {
return false;