Make WebAuthn clone detection actually block, and fix false positives
Two problems with sign-count clone detection: - suspicious_sign_count? flagged the case where both the stored and presented counts are 0. Most synced passkeys (Apple/Google) report 0 every time, so every legitimate sign-in was flagged — drowning real signals in noise. Per WebAuthn §6.1.1 a 0 counter means "no counter"; only flag when BOTH counts are non-zero and the new one does not advance. - On a suspicious count the controller only logged a warning and then continued to authenticate and overwrite the stored counter. A cloned credential therefore worked indefinitely. webauthn_verify now rejects the sign-in (no session, no counter update) and emails the user via a new SecurityMailer#suspicious_passkey_used. Tests cover the corrected classification (synced/first-use/normal vs equal/ decreasing) and the new alert email. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -54,6 +54,15 @@ class SecurityMailerTest < ActionMailer::TestCase
|
||||
assert_bodies_contain email, "Old MacBook"
|
||||
end
|
||||
|
||||
test "suspicious_passkey_used warns about a blocked clone sign-in" do
|
||||
email = SecurityMailer.suspicious_passkey_used(@user, nickname: "Yubikey-5", **CONTEXT)
|
||||
|
||||
assert_equal [@user.email_address], email.to
|
||||
assert_match(/blocked/i, email.subject)
|
||||
assert_bodies_contain email, "Yubikey-5"
|
||||
assert_bodies_match email, /clon/i
|
||||
end
|
||||
|
||||
test "api_key_created includes the key name" do
|
||||
email = SecurityMailer.api_key_created(@user, name: "CI bot", **CONTEXT)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user