security: prevent GitHub username swap attack on 7-day check #116
+122
−13
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 a vulnerability in the 7-day GitHub account age check that could be bypassed via username swapping.
The Attack:
created_atThe Fix:
authAccountstable to get the storedproviderAccountId(GitHub's immutable numeric user ID)idfield in the GitHub API responseChanges
convex/users.ts: AddgetGithubAccountIdInternalqueryconvex/lib/githubAccount.ts: Add ID verification checkconvex/lib/githubAccount.test.ts: Add tests for attack scenarioTest plan
🤖 Generated with Claude Code
Greptile Overview
Greptile Summary
This PR hardens the 7-day GitHub account age gate against username-swap attacks by looking up the immutable GitHub
providerAccountIdfromauthAccountsand comparing it to theidreturned byGET /users/:usernamebefore trustingcreated_at. It introduces a new internal query (getGithubAccountIdInternal) and adds unit tests covering both the mismatch (reject) and match (allow) scenarios.Overall the approach fits cleanly into the existing caching flow in
requireGitHubAccountAge: on stale cache, it fetches GitHub metadata, verifies identity, then storesgithubCreatedAt/githubFetchedAton the user.Confidence Score: 4/5
payload.idis missing, which could undermine the intended protection in some scenarios.(4/5) You can add custom instructions or style guidelines for the agent here!
Context used:
dashboard- AGENTS.md (source)