Skip to content

fix(expo): strip base64 padding from useLocalCredentials store keys - #10035

Open
RaphaelFakhri wants to merge 1 commit into
clerk:mainfrom
RaphaelFakhri:fix/expo-local-credentials-padded-key
Open

RaphaelFakhri wants to merge 1 commit into
clerk:mainfrom
RaphaelFakhri:fix/expo-local-credentials-padded-key

Conversation

@RaphaelFakhri

Copy link
Copy Markdown

Description

useLocalCredentials builds its secure-store keys from the raw publishable key. A publishable key ends with = when the base64 of <frontend host>$ needs padding. expo-secure-store only accepts keys that match /^[\w.-]+$/, so the synchronous getItem(key) call in the useState initializer throws during render and takes down the whole screen.

This change removes the = characters from the publishable key before it builds the two store keys, the same way the offline resource cache already does. Keys without padding don't change, so credentials that are already stored stay readable.

The new test mocks expo-secure-store with the same key validation as the real module. It fails on the parent commit and passes with this change.

Fixes #10033

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

@vercel

vercel Bot commented Oct 2, 2026

Copy link
Copy Markdown

@RaphaelFakhri is attempting to deploy a commit to the Clerk Production Team on Vercel.

A member of the Team first needs to authorize it.

@changeset-bot

changeset-bot Bot commented Oct 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c254796

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@clerk/expo Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

🧰 Additional context used
📚 Code guidelines (1)
.cursor/rules/typescript.mdc — auto-discovered

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 0ab4976a-a9dc-4465-830a-3a3be0dbc90b

📥 Commits

Reviewing files that changed from the base of the PR and between 46ff86f and c254796.

📒 Files selected for processing (3)
  • .changeset/expo-local-credentials-padded-publishable-key.md
  • packages/expo/src/local-credentials/useLocalCredentials/__tests__/useLocalCredentials.test.ts
  • packages/expo/src/local-credentials/useLocalCredentials/useLocalCredentials.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

useLocalCredentials removes = characters from the publishable key before using it in the SecureStore keys for the identifier and password. The test mock rejects keys outside SecureStore’s accepted pattern. A new test checks that a padded publishable key can be used to store credentials and that the resulting keys match the pattern. A patch changeset records the fix for @clerk/expo.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to c2547

Padded publishable keys now produce SecureStore-safe names, while unpadded keys retain their existing names. No concrete merge-blocking risk remains.

Security Architecture Review

Security architecture risk: 🔵 Low · up to c2547

The change consistently updates credential storage names without weakening biometric protection or changing the sign-in flow. Remaining uncertainty concerns storage compatibility and rollback for padded keys, rather than an established new attack path.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • observed — The inspected change directly affects the on-device identifier and password records selected by the current Clerk publishable key. The publishable-key source remains the existing Clerk context; this diff adds no new input source or credential recipient.

Trust Boundaries and Controls

  • observed — Credential writes still require enrolled biometrics. Password storage retains requireAuthentication and device-only accessibility while a passcode is set. Reading credentials still leads to Clerk password sign-in rather than directly establishing an authenticated session.

Resilience and Maintainability Implications

  • inferred — Both base and head use separate password and identifier writes and independent deletes without transactional coordination. Interruption after a password write or overlapping operations can leave incomplete or mismatched records. These lifecycle limitations predate this PR; the exact diff does not change their ordering or cleanup behavior.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly explains the SecureStore key failure, the padding fix, test coverage, compatibility behavior, and linked issue.
Title check ✅ Passed The title clearly and concisely states that the Expo fix strips Base64 padding from useLocalCredentials store keys.
Linked Issues check ✅ Passed The PR satisfies issue [#10033]. useLocalCredentials removes = characters before composing both SecureStore keys. Unpadded keys remain unchanged. The synchronous getItem call therefore receives …
Out of Scope Changes check ✅ Passed The changes stay within issue [#10033]. The implementation changes only the two useLocalCredentials SecureStore keys. The test adds regression coverage for the reported failure. The changeset docume…
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the expo label Oct 2, 2026
@pkg-pr-new

pkg-pr-new Bot commented Oct 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@10035

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@10035

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@10035

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@10035

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@10035

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@10035

@clerk/eslint-plugin

npm i https://pkg.pr.new/@clerk/eslint-plugin@10035

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@10035

@clerk/expo-biometrics

npm i https://pkg.pr.new/@clerk/expo-biometrics@10035

@clerk/expo-google-signin

npm i https://pkg.pr.new/@clerk/expo-google-signin@10035

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@10035

@clerk/express

npm i https://pkg.pr.new/@clerk/express@10035

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@10035

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@10035

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@10035

@clerk/mosaic

npm i https://pkg.pr.new/@clerk/mosaic@10035

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@10035

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@10035

@clerk/react

npm i https://pkg.pr.new/@clerk/react@10035

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@10035

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@10035

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@10035

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@10035

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@10035

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@10035

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@10035

commit: c254796

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[expo] useLocalCredentials throws "Invalid key provided to SecureStore" during render when the publishable key has base64 padding (=)

2 participants