fix: run dummy bcrypt.compare on unknown user to prevent timing side-channel

This commit is contained in:
toanhoang
2026-08-04 06:39:08 -04:00
parent 44dd33dd3b
commit 2a0acd11a9
2 changed files with 36 additions and 0 deletions
+16
View File
@@ -115,4 +115,20 @@ describe("verifyUserCredentials", () => {
expect(await verifyUserCredentials(email, undefined)).toBeNull();
expect(await verifyUserCredentials(123, password)).toBeNull();
});
// Timing side-channel fix: an unknown email must not short-circuit to a
// different outcome shape than a known email with the wrong password —
// both must be indistinguishable (null) so a caller/attacker can't infer
// which case occurred from the result alone. (The actual timing-safety
// property — running a dummy bcrypt.compare() on the unknown-email path —
// isn't asserted here since timing isn't reliably testable in a unit
// test; this only pins down the observable behavior staying identical.)
it("returns the same result (null) for an unknown email as for a known email with the wrong password", async () => {
const unknownEmailResult = await verifyUserCredentials("[email protected]", password);
const wrongPasswordResult = await verifyUserCredentials(email, "wrong-password");
expect(unknownEmailResult).toBeNull();
expect(wrongPasswordResult).toBeNull();
expect(unknownEmailResult).toBe(wrongPasswordResult);
});
});