Skip to content

fix: bump authkit-js to ^0.20.1 and harden returnTo redirects - #101

Merged
gjtorikian merged 2 commits into
mainfrom
devin/sec-1300-bump-authkit-js-harden-redirects
Jul 22, 2026
Merged

fix: bump authkit-js to ^0.20.1 and harden returnTo redirects#101
gjtorikian merged 2 commits into
mainfrom
devin/sec-1300-bump-authkit-js-harden-redirects

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Summary

Automated first-pass security fix for SEC-1300. Requires human security review before merge.

authkit-react exact-pinned @workos-inc/authkit-js to 0.20.0, freezing every consumer on a version with two confirmed defects that were fixed upstream in 0.20.1 (commit 138b602, PR #122):

  1. Logout-allowlist bypass → open redirect / javascript: XSS. In 0.20.0, signOut({ returnTo }) for a logged-out user (no access token in memory) calls window.location.assign(returnTo) on the raw, unvalidated value — bypassing the WorkOS logout-redirect allowlist that devs reasonably assume always validates returnTo.
  2. Auth-bootstrap DoS via malformed state. In 0.20.0, the callback handler does JSON.parse(stateParam) unguarded; a crafted link (?code=x&state=%7Bnot-json) throws, which — combined with the provider having no .catch() — permanently wedges the app on isLoading: true for that navigation.

Both were reproduced against the real 0.20.0 bundle and confirmed rejected on 0.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 the createClient() promise so an init failure settles into an unauthenticated state instead of wedging isLoading: 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: the onRedirectCallback example previously taught window.location.href = state.returnTo with no validation (seeding open-redirect/XSS into consumer apps). Now validates state.returnTo is same-origin before navigating, plus a security note that state is untrusted URL input.

Testing

  • npm run build — success.
  • npm run format:check — clean.
  • Reproduced the signOut open-redirect + javascript: XSS and the state DoS against the built 0.20.0 bundle (real browser + jsdom); verified 0.20.1 throws NoSessionError / treats malformed state as 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

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.
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author
Original prompt from Linear User

Please work on ticket "authkit-react hard-pins authkit-js 0.20.0, shipping the known-fixed unvalidated signOut({ returnTo }) redirect (logout-allowlist bypass enabling XSS/open redirect) plus an auth-callback state parse DoS to all consumers" (SEC-1300)

@playbook:playbook-b588614117c7477a9b9729928385384f

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@linear-code

linear-code Bot commented Jul 22, 2026

Copy link
Copy Markdown

SEC-1300

@devin-ai-integration devin-ai-integration Bot changed the title Bump authkit-js to ^0.20.1 and harden returnTo redirects fix: bump authkit-js to ^0.20.1 and harden returnTo redirects Jul 22, 2026
@greptile-apps

greptile-apps Bot commented Jul 22, 2026

Copy link
Copy Markdown

Greptile Summary

This PR upgrades the authentication client and hardens initialization and redirect handling.

  • Upgrades @workos-inc/authkit-js from 0.20.0 to ^0.20.1.
  • Prevents superseded client initialization promises from updating provider state.
  • Settles initialization failures into an unauthenticated state.
  • Documents same-origin validation for callback redirects.

Confidence Score: 5/5

This looks safe to merge.

  • The cleanup guard covers both successful and failed stale initializations.
  • No blocking issue remains in the updated code.

Important Files Changed

Filename Overview
src/provider.tsx Guards promise settlement after cleanup and handles client initialization failures.
package.json Updates the authentication client dependency to the patched release range.
package-lock.json Locks the authentication client to version 0.20.1.
README.md Adds same-origin redirect validation and warns that callback state is untrusted.

Reviews (2): Last reviewed commit: "fix: ignore stale createClient results a..." | Re-trigger Greptile

Comment thread src/provider.tsx
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).
@gjtorikian
gjtorikian merged commit 5481fa8 into main Jul 22, 2026
4 checks passed
@gjtorikian
gjtorikian deleted the devin/sec-1300-bump-authkit-js-harden-redirects branch July 22, 2026 20:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant