Bitwarden import: non-UUID `credentialId` silently becomes the null UUID, breaking imported passkeys
Have you searched for an existing issue?
- Yes, I tried searching and reviewed the pinned issues
Brief Summary
Summary
BitwardenReader.cpp:92-98 treats login.fido2Credentials.credentialId as a UUID. My export contained a credentialId in a different form — base64url with a b64. prefix. The conversion does not fail on it; it produces the null UUID, so the entry imports without error and KPEX_PASSKEY_CREDENTIAL_ID ends up as AAAAAAAAAAAAAAAAAAAAAA. The passkey then cannot authenticate.
Root cause
const auto credentialUuid = Tools::uuidToHex(credentialIdValue); // QString -> QUuid, implicit
const auto credentialIdArray = QByteArray::fromHex(credentialUuid.toUtf8());Tools::uuidToHex() takes a QUuid. The QString is converted implicitly, and an unparseable value yields a null QUuid rather than an error. toRfc4122() returns 16 zero bytes, the hex round-trip preserves them, and the base64url encoding is 22 A characters. Nothing on the path reports a failure.
This affects any credentialId that is not a UUID, not only the b64. form.
Environment
- KeePassXC 2.7.12, Windows
- Source vault: Bitwarden Password Manager for Android 2026.8.1 (21856)
Related
#10775 and discussion #10716 consider only the UUID form.
Steps to Reproduce
- Bitwarden vault export, unencrypted
.json, containing a passkey whosecredentialIdisb64.-prefixed base64url rather than a UUID. - KeePassXC 2.7.12: Database → Import → Bitwarden (.json).
- Entry → Advanced:
KPEX_PASSKEY_CREDENTIAL_ID=AAAAAAAAAAAAAAAAAAAAAA. - Authentication with the imported passkey fails.
tests/data/bitwarden_passkey_export.json covers the UUID form only, so this variant is untested.
Expected Versus Actual Behavior
No response
KeePassXC Debug Information
Operating System
Windows
Linux Desktop Environment
None
Linux Windowing System
None
Source: keepassxreboot/keepassxc