Uh oh!
There was an error while loading. Please reload this page.
fix: bump authkit-js to ^0.20.1 and harden returnTo redirects - #101
Conversation
Ship the upstream authkit-js 0.20.1 fixes to all consumers and remove two consumer-facing footguns.
- Bump @workos-inc/authkit-js from the exact pin 0.20.0 to ^0.20.1. The exact pin froze consumers on 0.20.0, which shipped an unvalidated signOut({ returnTo }) redirect for logged-out users (logout-allowlist bypass -> open redirect / javascript: XSS) and an unguarded JSON.parse of the callback state param (auth-bootstrap DoS on a crafted link). Both are fixed in 0.20.1; a caret range lets future patches flow.
- Add a .catch() to the provider's createClient() promise so an initialization failure can no longer wedge the app on isLoading:true.
- Harden the README onRedirectCallback example to validate state.returnTo against the app origin before navigating.Original prompt from Linear User
|
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Greptile SummaryThis PR upgrades the authentication client and hardens initialization and redirect handling.
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (2): Last reviewed commit: "fix: ignore stale createClient results a..." | Re-trigger Greptile |
Uh oh!
There was an error while loading. Please reload this page.
Guard the provider's createClient() then/catch handlers with a per-effect cancelled flag so a superseded initialization that settles late cannot clobber the current one's state (flagged in review).
Summary
Automated first-pass security fix for SEC-1300. Requires human security review before merge.
authkit-reactexact-pinned@workos-inc/authkit-jsto0.20.0, freezing every consumer on a version with two confirmed defects that were fixed upstream in0.20.1(commit138b602, PR #122):javascript:XSS. In0.20.0,signOut({ returnTo })for a logged-out user (no access token in memory) callswindow.location.assign(returnTo)on the raw, unvalidated value — bypassing the WorkOS logout-redirect allowlist that devs reasonably assume always validatesreturnTo.state. In0.20.0, the callback handler doesJSON.parse(stateParam)unguarded; a crafted link (?code=x&state=%7Bnot-json) throws, which — combined with the provider having no.catch()— permanently wedges the app onisLoading: truefor that navigation.Both were reproduced against the real
0.20.0bundle and confirmed rejected on0.20.1(see Linear ticket for full attacker-perspective PoC).Changes
package.json/ lockfile:"@workos-inc/authkit-js": "0.20.0"→"^0.20.1". The caret both delivers the fixes and lets future patches flow instead of re-freezing consumers.src/provider.tsx: add a.catch()to thecreateClient()promise so an init failure settles into an unauthenticated state instead of wedgingisLoading: true(defense-in-depth for the DoS):}).then(async (client) => { ... setState((prev) => ({ ...prev, isLoading: false, user })); - });+ }).catch((error) => {+ console.error(error);+ setState((prev) => ({ ...prev, isLoading: false, user: null }));+ });README.md: theonRedirectCallbackexample previously taughtwindow.location.href = state.returnTowith no validation (seeding open-redirect/XSS into consumer apps). Now validatesstate.returnTois same-origin before navigating, plus a security note thatstateis untrusted URL input.Testing
npm run build— success.npm run format:check— clean.signOutopen-redirect +javascript:XSS and thestateDoS against the built0.20.0bundle (real browser + jsdom); verified0.20.1throwsNoSessionError/ treats malformedstateas absent.This is an automated first-pass fix; a human security reviewer should confirm before merge.
Link to Devin session: https://app.devin.ai/sessions/5de3ea20d3ad44aa81cb15e4b4da448a