fix: run dummy bcrypt.compare on unknown user to prevent timing side-channel
This commit is contained in:
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user