Skip to content

fix(auth): measure Windows keychain limit in UTF-16 bytes and clear stale entry on fallback#12

Merged
phil-accelbyte merged 1 commit into
mainfrom
fix/windows-keychain-utf16-limit
Jun 23, 2026
Merged

fix(auth): measure Windows keychain limit in UTF-16 bytes and clear stale entry on fallback#12
phil-accelbyte merged 1 commit into
mainfrom
fix/windows-keychain-utf16-limit

Conversation

@phil-accelbyte

Copy link
Copy Markdown
Collaborator

Problem

The Windows Credential Manager guard measured the token blob with UTF-8 str::len() against the 2560-byte limit, but keyring's windows-native backend stores the password as a UTF-16 blob and rejects values whose UTF-16 byte length exceeds 2560. For ASCII that guard is 2× too lenient: a token JSON of ~1281–2560 chars passed the check, reached the keychain, failed the write, and silently fell back to file storage while leaving the old keychain entry in place.

Reads are keychain-first, so the stale entry shadowed the fresh file token — its rotated refresh token was then sent on the next refresh and the server rejected it (Session expired and token refresh failed). Windows-only; it surfaced as token JSONs grew past ~1280 chars.

Fix

  • Measure the blob via credman_blob_bytes (UTF-16 bytes), matching keyring's own check.
  • Clear any stale keychain entry on every file-storage fallback (not just the over-limit branch) so it can never shadow the file token on a later read.

Tests

  • credman_blob_bytes is twice the ASCII length.
  • A 1300-char token sits in the UTF-16 "dead zone" (UTF-8 under the limit, UTF-16 over) and now trips the guard.
  • File-fallback round-trip: the refresh token survives storage and reads back unchanged.

…tale entry on fallback

The Windows Credential Manager guard used UTF-8 str::len() against the
2560-byte limit, but keyring's windows-native backend stores the password
as UTF-16 and rejects values whose UTF-16 blob exceeds 2560 bytes. For
ASCII that is 2x too lenient: a token JSON of ~1281-2560 chars passed the
guard, reached the keychain, failed the write, and silently fell back to
file storage while leaving the old keychain entry in place. Reads are
keychain-first, so the stale entry shadowed the fresh file token and its
rotated refresh token was rejected on the next refresh ("Session expired
and token refresh failed").

- Measure the blob via credman_blob_bytes (UTF-16 bytes), matching keyring.
- Clear any stale keychain entry on every file-storage fallback so it can
  never shadow the file token on read.
@phil-accelbyte
phil-accelbyte merged commit 5c13534 into main Jun 23, 2026
5 checks passed
@phil-accelbyte
phil-accelbyte deleted the fix/windows-keychain-utf16-limit branch June 23, 2026 12:19
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.

1 participant