Resident credentials are silently overwritten along user.id prefix chain (raspi_1 → raspi_12 → raspi_123) on v7.0 #241

Closed
opened 2026-01-05 12:18:53 +08:00 by MadMechatronic · 5 comments
MadMechatronic commented 2026-01-05 12:18:53 +08:00 (Migrated from github.com)

Summary (TL;DR)

On pico-fido v7.0, discoverable (resident) credentials are incorrectly deduplicated based on a prefix of user.id.
Registering raspi_12 overwrites raspi_1, and registering raspi_123 then overwrites raspi_12.
Only one resident credential per prefix chain is kept, causing silent and irreversible data loss.


Description

When using pico-fido v7.0 on a Raspberry Pi Pico, creating discoverable (resident) credentials whose user.id values share a common prefix results in silent overwriting of existing credentials instead of allocating new resident slots.

This happens even when plenty of resident credential slots are free and occurs with default WebAuthn settings.

The overwrite is deterministic and repeatable and forms a chain:

  • raspi_12 overwrites raspi_1
  • raspi_123 overwrites raspi_12

This indicates faulty resident credential matching or deduplication logic.

The same test sequence performed on a real YubiKey 5 behaves correctly (no overwrites, new credentials are added).


Environment


Steps to Reproduce

  1. Flash pico_fido_pico-7.0.uf2 to a Raspberry Pi Pico and set a PIN.

  2. On https://webauthn.io, register discoverable credentials for:

    • raspi_1
    • raspi_2
  3. Verify credentials:

    fido2-token -L -k webauthn.io /dev/hidrawX
    
  4. Register another discoverable credential for:

    • raspi_12
  5. List credentials again:

    fido2-token -L -k webauthn.io /dev/hidrawX
    

    raspi_1 has been overwritten by raspi_12

  6. Register another discoverable credential for:

    • raspi_123
  7. List credentials again:

    fido2-token -L -k webauthn.io /dev/hidrawX
    

    raspi_12 has now been overwritten by raspi_123

  8. (Control test) Register:

    • raspi_01
      This coexists and is not part of the overwrite chain.

Expected Result

Each registration allocates a new resident credential slot.
All previously registered credentials remain present.

Example expected set:

  • raspi_1
  • raspi_12
  • raspi_123
  • raspi_2
  • raspi_01

Actual Result

Resident credentials are silently overwritten when the new user.id extends an existing one.

Observed behavior:

  • raspi_12 overwrites raspi_1
  • raspi_123 overwrites raspi_12
  • Slot count does not increase
  • Data loss occurs without warning

Example state after registering raspi_123:

00: … (null) d2ViYXV0aG5pby1yYXNwaV8xMjM=   # webauthnio-raspi_123
01: … (null) d2ViYXV0aG5pby1yYXNwaV8y       # webauthnio-raspi_2
02: … (null) d2ViYXV0aG5pby1yYXNwaV8wMQ==   # webauthnio-raspi_01

raspi_1 and raspi_12 are lost.


Additional Evidence

New keypair is generated but stored by overwriting

Running:

fido2-token -I -k webauthn.io -i <credential-id> /dev/hidrawX

shows a new public key for raspi_12 / raspi_123, confirming that:

  • a fresh credential is generated
  • but it is written into an existing resident slot instead of a new one

Reference Device Comparison

The same registration sequence tested on a YubiKey 5:

  • correctly allocates new resident credentials
  • does not overwrite existing entries

This suggests the issue is specific to pico-fido’s resident credential storage or matching logic.


Debug Output

For additional context, I am attaching debug output captured from the test token after testing (only webauthn.io test credentials present):
fido2-token_debug.txt


Notes / Observations

  • Overwrite occurs only for prefix-extended user.id values:
    • raspi_1raspi_12raspi_123 overwrite chain
    • raspi_01 coexists
  • This strongly suggests incorrect resident credential matching, likely based on prefix or length comparison rather than full (rpId, user.id) equality.
  • According to WebAuthn/FIDO2, resident credentials must not be overwritten unless (rpId, user.id) is identical.

Impact

  • Silent loss of resident credentials
  • Potential account lockout
  • Violates expected authenticator behavior
  • Reproducible with default WebAuthn settings
## Summary (TL;DR) On pico-fido v7.0, discoverable (resident) credentials are incorrectly deduplicated based on a **prefix of `user.id`**. Registering `raspi_12` overwrites `raspi_1`, and registering `raspi_123` then overwrites `raspi_12`. Only one resident credential per prefix chain is kept, causing silent and irreversible data loss. --- ## Description When using **pico-fido v7.0** on a Raspberry Pi Pico, creating discoverable (resident) credentials whose `user.id` values share a common prefix results in **silent overwriting of existing credentials** instead of allocating new resident slots. This happens even when plenty of resident credential slots are free and occurs with default WebAuthn settings. The overwrite is **deterministic and repeatable** and forms a chain: * `raspi_12` overwrites `raspi_1` * `raspi_123` overwrites `raspi_12` This indicates faulty resident credential matching or deduplication logic. The same test sequence performed on a **real YubiKey 5** behaves correctly (no overwrites, new credentials are added). --- ## Environment * Release / Tag: **v7.0** [https://github.com/polhenarejos/pico-fido/releases/tag/v7.0](https://github.com/polhenarejos/pico-fido/releases/tag/v7.0) * Firmware used: `pico_fido_pico-7.0.uf2` [https://github.com/polhenarejos/pico-fido/releases/download/v7.0/pico_fido_pico-7.0.uf2](https://github.com/polhenarejos/pico-fido/releases/download/v7.0/pico_fido_pico-7.0.uf2) * Device: Raspberry Pi Pico (RP2040) * RP: `webauthn.io` * OS: Arch Linux * Browser: Chromium / Firefox (reproduces in both) * Tooling: `fido2-token` (libfido2) * Discoverable (resident) credentials enabled * Free resident slots available (e.g. 2/25 used) --- ## Steps to Reproduce 1. Flash `pico_fido_pico-7.0.uf2` to a Raspberry Pi Pico and set a PIN. 2. On `https://webauthn.io`, register discoverable credentials for: * `raspi_1` * `raspi_2` 3. Verify credentials: ```bash fido2-token -L -k webauthn.io /dev/hidrawX ``` 4. Register another discoverable credential for: * `raspi_12` 5. List credentials again: ```bash fido2-token -L -k webauthn.io /dev/hidrawX ``` → `raspi_1` has been overwritten by `raspi_12` 6. Register another discoverable credential for: * `raspi_123` 7. List credentials again: ```bash fido2-token -L -k webauthn.io /dev/hidrawX ``` → `raspi_12` has now been overwritten by `raspi_123` 8. (Control test) Register: * `raspi_01` This **coexists** and is not part of the overwrite chain. --- ## Expected Result Each registration allocates a **new resident credential slot**. All previously registered credentials remain present. Example expected set: * `raspi_1` * `raspi_12` * `raspi_123` * `raspi_2` * `raspi_01` --- ## Actual Result Resident credentials are **silently overwritten** when the new `user.id` extends an existing one. Observed behavior: * `raspi_12` overwrites `raspi_1` * `raspi_123` overwrites `raspi_12` * Slot count does not increase * Data loss occurs without warning Example state after registering `raspi_123`: ```text 00: … (null) d2ViYXV0aG5pby1yYXNwaV8xMjM= # webauthnio-raspi_123 01: … (null) d2ViYXV0aG5pby1yYXNwaV8y # webauthnio-raspi_2 02: … (null) d2ViYXV0aG5pby1yYXNwaV8wMQ== # webauthnio-raspi_01 ``` `raspi_1` and `raspi_12` are lost. --- ## Additional Evidence ### New keypair is generated but stored by overwriting Running: ```bash fido2-token -I -k webauthn.io -i <credential-id> /dev/hidrawX ``` shows a **new public key** for `raspi_12` / `raspi_123`, confirming that: * a fresh credential is generated * but it is written into an existing resident slot instead of a new one --- ## Reference Device Comparison The same registration sequence tested on a **YubiKey 5**: * correctly allocates new resident credentials * does **not** overwrite existing entries This suggests the issue is specific to pico-fido’s resident credential storage or matching logic. --- ## Debug Output For additional context, I am attaching debug output captured from the test token after testing (only webauthn.io test credentials present): [fido2-token_debug.txt](https://github.com/user-attachments/files/24426655/fido2-token_debug.txt) --- ## Notes / Observations * Overwrite occurs only for prefix-extended `user.id` values: * `raspi_1` → `raspi_12` → `raspi_123` ❌ overwrite chain * `raspi_01` ✅ coexists * This strongly suggests incorrect resident credential matching, likely based on prefix or length comparison rather than full `(rpId, user.id)` equality. * According to WebAuthn/FIDO2, resident credentials must not be overwritten unless `(rpId, user.id)` is identical. --- ## Impact * Silent loss of resident credentials * Potential account lockout * Violates expected authenticator behavior * Reproducible with default WebAuthn settings
polhenarejos commented 2026-01-05 19:37:33 +08:00 (Migrated from github.com)

Fixed in ac7e345.

Thanks for the very well detailed report. It helped a lot.

Fixed in [ac7e345](https://github.com/polhenarejos/pico-fido/commit/ac7e34522a4f1847d280250b230400008eebc87d). Thanks for the very well detailed report. It helped a lot.
wlatendresse commented 2026-01-05 19:50:48 +08:00 (Migrated from github.com)

@polhenarejos

I also read this bug report and thought, "This is how all bug reports should look like."

Perhaps it would be useful to create a report template from this report so that all bug reports are as detailed and comprehensive as possible?

And additionally, the existence of the template could be mentioned somewhere in the project's README.md file so that everyone is aware of it?

At least that's how I intend to structure my projects here on GitHub (and on alternatives).

@polhenarejos I also read this bug report and thought, "This is how all bug reports should look like." Perhaps it would be useful to create a report template from this report so that all bug reports are as detailed and comprehensive as possible? And additionally, the existence of the template could be mentioned somewhere in the project's README.md file so that everyone is aware of it? At least that's how I intend to structure my projects here on GitHub (and on alternatives).
MadMechatronic commented 2026-01-06 01:54:01 +08:00 (Migrated from github.com)

Thanks for the quick fix, @polhenarejos

I tested updated builds based on the current main branch, and the issue is now resolved. Resident credentials with shared prefixes no longer overwrite each other and behave as expected.

I initially discovered this issue while testing an older state of pico-fido2. Since that repository no longer contains code, I reproduced and verified the problem using the current pico-fido release (v7.0), where the issue was still present.

I also backported the fix to my local pico-fido2 setup, where it resolves the issue as well.

Unrelated question: is there any chance that pico-fido2 might be revived in the future, or should i consider it permanently discontinued?

Thanks for the quick fix, @polhenarejos I tested updated builds based on the current main branch, and the issue is now resolved. Resident credentials with shared prefixes no longer overwrite each other and behave as expected. I initially discovered this issue while testing an older state of pico-fido2. Since that repository no longer contains code, I reproduced and verified the problem using the current pico-fido release (v7.0), where the issue was still present. I also backported the fix to my local pico-fido2 setup, where it resolves the issue as well. Unrelated question: is there any chance that pico-fido2 might be revived in the future, or should i consider it permanently discontinued?
polhenarejos commented 2026-01-06 06:59:11 +08:00 (Migrated from github.com)

@polhenarejos

I also read this bug report and thought, "This is how all bug reports should look like."

Perhaps it would be useful to create a report template from this report so that all bug reports are as detailed and comprehensive as possible?

And additionally, the existence of the template could be mentioned somewhere in the project's README.md file so that everyone is aware of it?

At least that's how I intend to structure my projects here on GitHub (and on alternatives).

I agree on that a detailed issue is always welcome, provides a valuable help and reduces drastically the interaction focusing on solving the bug. However, I want to be accessible as much as posible. There are users that are not skilled or even they use it as a consumer. Others have problems expressing themselves in english. If I put a template, it will create a barrier that may discourage some to report bugs they found. My goal is to gather many bugs as possible and later I'll figure out how to solve them, if I can. I do not expect users have the proper tools to debug, probe or rebuild the software with variants. In the end, I only need the reproduceability.

> [@polhenarejos](https://github.com/polhenarejos) > > I also read this bug report and thought, "This is how all bug reports should look like." > > Perhaps it would be useful to create a report template from this report so that all bug reports are as detailed and comprehensive as possible? > > And additionally, the existence of the template could be mentioned somewhere in the project's README.md file so that everyone is aware of it? > > At least that's how I intend to structure my projects here on GitHub (and on alternatives). I agree on that a detailed issue is always welcome, provides a valuable help and reduces drastically the interaction focusing on solving the bug. However, I want to be accessible as much as posible. There are users that are not skilled or even they use it as a consumer. Others have problems expressing themselves in english. If I put a template, it will create a barrier that may discourage some to report bugs they found. My goal is to gather many bugs as possible and later I'll figure out how to solve them, if I can. I do not expect users have the proper tools to debug, probe or rebuild the software with variants. In the end, I only need the reproduceability.
wlatendresse commented 2026-01-06 16:49:22 +08:00 (Migrated from github.com)

@polhenarejos

Well, perhaps the README.md file could simply state that using the template is OPTIONAL and that filing out the template increases the likelihood of fixing the bug, simply by providing the necessary information. In other words, that filling out the template is in the best interest of the bug reporter. At the same time, your exact text could also be included there, clarifying that if the template is legitimately not used, the bug will still be investigated, but the lack of information simply makes it less likely that it will be fixed.

Or would that already be TL;DR?

@polhenarejos Well, perhaps the README.md file could simply state that using the template is OPTIONAL and that filing out the template increases the likelihood of fixing the bug, simply by providing the necessary information. In other words, that filling out the template is in the best interest of the bug reporter. At the same time, your exact text could also be included there, clarifying that if the template is legitimately not used, the bug will still be investigated, but the lack of information simply makes it less likely that it will be fixed. Or would that already be TL;DR?
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dearsky/pico-fido#241