fix(security): actually prevent timing leak — eagerly evaluate timingSafeEqual

The previous fix had a subtle bug: JavaScript && short-circuits,
so crypto.timingSafeEqual() was skipped when buffer lengths differed
(sameLength was false). The dummy buffer was allocated but never
compared, leaving the original length-based timing leak intact.

Now timingSafeEqual is eagerly assigned to a const before the &&
guard, guaranteeing it runs in constant time on every auth attempt
regardless of whether the length guess was correct.
This commit is contained in:
KoalaDev
2026-06-16 04:23:20 +02:00
parent cc97e0d371
commit dd8eefe3f9
+5 -1
View File
@@ -37,9 +37,13 @@ export function isAdminMetricsAuthorized(authHeader, adminToken) {
// timingSafeEqual throws on different-length buffers, so when lengths
// differ we compare against a zeroed buffer of the provided length
// (guaranteed mismatch, constant time).
// NOTE: timingSafeEqual must be evaluated eagerly (assigned to const)
// before the && short-circuit, otherwise it's skipped on length mismatch
// and the timing leak remains.
const sameLength = expectedBuffer.length === providedBuffer.length;
const compareBuf = sameLength ? expectedBuffer : Buffer.alloc(providedBuffer.length);
return sameLength && crypto.timingSafeEqual(compareBuf, providedBuffer);
const equal = crypto.timingSafeEqual(compareBuf, providedBuffer);
return sameLength && equal;
}
export function isAdminMetricsTokenStrong(adminToken, minLength = 32) {