fix(connect): hard-fail OAuth callback when Redis unavailable #478
Open
hariom888 wants to merge 6 commits into
Open
fix(connect): hard-fail OAuth callback when Redis unavailable #478hariom888 wants to merge 6 commits into
hariom888 wants to merge 6 commits into
Conversation
The CSRF nonce check in /connect/github/callback was guarded by if (app.redis && ...), meaning a Redis outage silently bypassed all CSRF verification. An attacker could craft a base64 state for any userId, submit a stolen OAuth code to the callback, and have a github_follow token stored under an arbitrary user's account. Changes: - Replace the conditional CSRF guard with an explicit hard-fail: if !app.redis || app.redis.status !== 'ready', return 503 immediately. The callback never reaches token exchange or DB writes without a verified nonce. - Remove all �pp.redis ? ... : null ternaries from the callback path — every Redis access is now unconditional, matching the initiator's strictness. - Nonce deletion ( edis.del) is now unconditional after a successful verification, preventing replay attacks. Tests added (connect.test.ts): - Redis unavailable (status !== 'ready') → 503, no upsert - Redis is null/falsy → 503, no upsert - Crafted state with unknown nonce → invalid_state redirect, no upsert - Nonce present but userId mismatch → invalid_state redirect, no upsert - Valid round-trip → connected=github redirect, nonce consumed - Nonce replay → second request rejected after first consumes the nonce - Missing code/state params → missing_params redirect - Malformed base64 state → connect_failed redirect
|
@hariom888 is attempting to deploy a commit to the Prashantkumar Khatri's projects Team on Vercel. A member of the Team first needs to authorize it. |
CI — Checks FailedBackend — FAIL
Mobile — SKIP
Web — SKIP
Last updated: |
Contributor
Author
Typecheck failure is pre-existing on
|
Harxhit
reviewed
Jun 7, 2026
Harxhit
left a comment
Collaborator
There was a problem hiding this comment.
Fix lint error in connect.ts file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #438.
/connect/github/callbackguarded its CSRF nonce check behindif (app.redis && ...). A Redis outage silently removed the entire guard while still allowing the OAuth exchange to proceed — withuserIdtaken directly from the attacker-controlled base64stateparameter. An attacker who could predict or observe the state format could store a token under any arbitrary user's account.Root cause
Fix
Hard-fail immediately if Redis is not ready. The callback cannot safely proceed without nonce verification.
This mirrors the strictness of the initiator (
GET /github), which already unconditionally callsapp.redis.set— making Redis a hard dependency for both ends of the flow.Test coverage
app.redisis nullinvalid_stateinvalid_stateconnected=github, nonce consumedinvalid_statemissing_paramsconnect_failedFiles changed
apps/backend/src/routes/connect.tsapps/backend/src/__tests__/connect.test.ts