Skip to content

fix(webauthn): largeBlob.read no longer leaks largeBlobKey to RP#198

Merged
AlfioEmanueleFresta merged 2 commits into
masterfrom
fix/webauthn-largeblob-key-disclosure
May 12, 2026
Merged

fix(webauthn): largeBlob.read no longer leaks largeBlobKey to RP#198
AlfioEmanueleFresta merged 2 commits into
masterfrom
fix/webauthn-largeblob-key-disclosure

Conversation

@AlfioEmanueleFresta
Copy link
Copy Markdown
Member

@AlfioEmanueleFresta AlfioEmanueleFresta commented May 10, 2026

Per WebAuthn L3 sec. 10.1.5 (largeBlob extension), the relying party expects the blob output to be the decrypted plaintext blob payload, fetched by the platform via the CTAP authenticatorLargeBlobs command using the per-credential largeBlobKey as an AES-256-GCM key. The library was instead writing the raw largeBlobKey into blob and never calling authenticatorLargeBlobs. That means an RP receives the AES key itself (not the blob), and if the RP can also read the device's largeBlobArray (publicly readable region of the authenticator over CTAP), it can decrypt and forge entries.

Until authenticatorLargeBlobs is wired up (follow-up PR #206), the safe behaviour is to set large_blob.blob = None. The CTAP-level model keeps the field so the follow-up can use it.

Changes

  • Stop routing largeBlobKey into the WebAuthn large_blob.blob output.
  • The CTAP-level Ctap2GetAssertionResponse.large_blob_key remains so the next PR can use it.
  • Regression test asserts the WebAuthn response no longer contains the key.

References

@AlfioEmanueleFresta AlfioEmanueleFresta marked this pull request as ready for review May 10, 2026 20:11
@AlfioEmanueleFresta AlfioEmanueleFresta marked this pull request as draft May 10, 2026 20:13
@AlfioEmanueleFresta AlfioEmanueleFresta force-pushed the fix/webauthn-largeblob-key-disclosure branch from 4f484fb to 63fd2d2 Compare May 10, 2026 20:26
@AlfioEmanueleFresta AlfioEmanueleFresta marked this pull request as ready for review May 10, 2026 21:09
Copy link
Copy Markdown
Collaborator

@msirringhaus msirringhaus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that's right. I was actually planning on finalizing my LargeBlob-PR, that would have fixed that, too, but that got delayed by other stuff. This is a good workaround until then

AlfioEmanueleFresta added a commit that referenced this pull request May 12, 2026
Per review on #198: keep the per-credential largeBlobKey only on the
CTAP-level Ctap2GetAssertionResponse. Surfacing it on the public
Assertion struct gives callers a foot-gun to forward straight to the
RP, which is exactly the disclosure this PR is meant to prevent. The
follow-up authenticatorLargeBlobs PR (#206) can read the key directly
off the CTAP response.
@AlfioEmanueleFresta AlfioEmanueleFresta force-pushed the fix/webauthn-largeblob-key-disclosure branch from 63fd2d2 to 34571aa Compare May 12, 2026 17:46
When the RP requests `largeBlob: { read: true }`, libwebauthn was populating
the WebAuthn response's `blob` field with the per-credential `largeBlobKey`
(a 32-byte AES-256-GCM key) instead of the decrypted blob payload. The CTAP
2.1 `authenticatorLargeBlobs` command is not yet implemented; until it is,
the safe behaviour is to drop the key from the WebAuthn response.

The CTAP-level `Ctap2GetAssertionResponse.large_blob_key` field is unchanged
so the next PR can wire up the proper flow.

Refs: WebAuthn L3 sec. 10.1.5, CTAP 2.1 sec. 6.10.
Per review on #198: keep the per-credential largeBlobKey only on the
CTAP-level Ctap2GetAssertionResponse. Surfacing it on the public
Assertion struct gives callers a foot-gun to forward straight to the
RP, which is exactly the disclosure this PR is meant to prevent. The
follow-up authenticatorLargeBlobs PR (#206) can read the key directly
off the CTAP response.
@AlfioEmanueleFresta AlfioEmanueleFresta force-pushed the fix/webauthn-largeblob-key-disclosure branch from 34571aa to 5388273 Compare May 12, 2026 17:47
@AlfioEmanueleFresta AlfioEmanueleFresta merged commit 8640a90 into master May 12, 2026
4 checks passed
@AlfioEmanueleFresta AlfioEmanueleFresta deleted the fix/webauthn-largeblob-key-disclosure branch May 12, 2026 17:51
AlfioEmanueleFresta added a commit that referenced this pull request May 12, 2026
- GetAssertionRequest.cross_origin renamed to top_origin (#188)
- Assertion no longer carries large_blob_key (#198); thread it
  through from Ctap2GetAssertionResponse instead
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants