Severity: Low
File: backend/src/lib/downloadTokens.ts:39-41
CWE: CWE-208 — Observable Timing Discrepancy
OWASP: A02:2021 — Cryptographic Failures
Description
The HMAC comparison function exits early if the string lengths differ, before reaching the constant-time comparison:
function timingSafeEqStr(a: string, b: string): boolean {
if (a.length !== b.length) return false; // early exit — timing leak
return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));
}
Impact
A network-positioned attacker can distinguish "wrong length" responses from "correct length but wrong value" responses by measuring timing. In practice, SHA-256 always produces 32 bytes → 43-char base64url, so this leaks no useful information for standard token forgery attempts. The risk is low and theoretical, but the pattern violates the contract of a constant-time comparison and should be corrected.
Fix
Remove the early length check. Perform the comparison unconditionally, padding to equal length:
function timingSafeEqStr(a: string, b: string): boolean {
const aBuf = Buffer.from(a);
const bBuf = Buffer.alloc(aBuf.length);
Buffer.from(b).copy(bBuf);
// Compare in constant time; also verify lengths match
return crypto.timingSafeEqual(aBuf, bBuf) && a.length === b.length;
}
Remediation tier: Backlog — low priority, no immediate exploit path.
Severity: Low
File:
backend/src/lib/downloadTokens.ts:39-41CWE: CWE-208 — Observable Timing Discrepancy
OWASP: A02:2021 — Cryptographic Failures
Description
The HMAC comparison function exits early if the string lengths differ, before reaching the constant-time comparison:
Impact
A network-positioned attacker can distinguish "wrong length" responses from "correct length but wrong value" responses by measuring timing. In practice, SHA-256 always produces 32 bytes → 43-char base64url, so this leaks no useful information for standard token forgery attempts. The risk is low and theoretical, but the pattern violates the contract of a constant-time comparison and should be corrected.
Fix
Remove the early length check. Perform the comparison unconditionally, padding to equal length:
Remediation tier: Backlog — low priority, no immediate exploit path.