clients
clients copied to clipboard
User Verification PIN implementation is not compliant with FIDO specs
Steps To Reproduce
Register a passkey at passkeys.io and store it in your Bitwarden browser extension, then perform the following tests (sign out after each successful login):
- Set an arbitrary vault unlock PIN, then start a stopwatch when clicking the "Sign in with a passkey" button on passkeys.io. Confirm the passkey to be used, enter the PIN at the prompt — but do not click Submit or hit Enter. When the stopwatch indicates that the elapsed time is in the range 31–59 seconds, click Submit.
- Set an arbitrary vault unlock PIN, then click the "Sign in with a passkey" button on passkeys.io, and confirm the passkey to be used. Deliberately enter and submit an incorrect PIN; repeat as many times as possible before the 60-second timeout (in my tests, I achieved approximately 25 consecutive submissions of incorrect PINs). Now repeat the passkey login (by clicking the "Sign in with a passkey" button again), this time entering the correct user verification PIN.
- Set a vault unlock PIN that consists of a single character (e.g.,
0
). Use the "Sign in with a passkey" option on passkeys.io, and enter the PIN when prompted for user verification. - Set a vault unlock PIN that consists of more than 64 characters (my tests reached PIN lengths up to 5,279 characters). Use the "Sign in with a passkey" option on passkeys.io, and enter the PIN when prompted for user verification.
Expected Result
Per the FIDO CTAP specifications, the following authenticator behaviors are mandated. Here, I am referencing the 21 June 2022 Proposed Standard, so there may be a more relevant document for standards currently in force; however, I believe that any differences do not significantly affect the issues raised in this report.
Expected Test Results:
- The authenticator should time out if the user verification has not been completed within 30 seconds (6.5.2.1).
- If the number of incorrect PIN retries is greater than
8
, then the authenticator's user verification PIN should be disabled, requiring the entire authenticator to be reset (6.5.2.2). - Authenticators should not allow user verification PINs shorter than 4 Unicode characters (6.5.1).
- Authenticators should not allow user verification PINs longer than 63 bytes (6.5.1).
Actual Result
Testing indicates that none of the above specifications are met. The actual test results are:
- The user verification PIN is accepted for up to 60 seconds (from the time that "Sign in with a passkey" is clicked), resulting in a successful passkey login.
- After submitting more than 8 incorrect retries of the user verification PIN, the PIN still works for logging in with a passkey. The PIN is not disabled, and there is no sign that the authenticator has been "reset".
- User verification PINs shorter than 4 characters can be successfully used for passkey login.
- User verification PINs much longer than 63 bytes can be successfully used for passkey login.
Screenshots or Videos
No response
Additional Context
The underlying issue is that the requirements for the CTAP user verification PIN are fundamentally different from the requirements for the Bitwarden vault unlock PIN (or the Bitwarden master password). Therefore, using the vault unlock PIN or the master password for CTAP user verification is a flawed design. A separate PIN should be used for passkey user verification; ideally, an encrypted version of this UV PIN (or its hash) should be stored in the vault and syncable, so that the same passkey PIN can be used across all devices.
Operating System
Windows
Operating System Version
No response
Web Browser
Chrome
Browser Version
No response
Build Version
2024.6.0
Issue Tracking Info
- [X] I understand that work is tracked outside of Github. A PR will be linked to this issue should one be opened to address it, but Bitwarden doesn't use fields like "assigned", "milestone", or "project" to track progress.