Repository navigation
Conversation
createMigration checked that the caller controls ownerAddress, but never that ownerAddress belongs to the wallet being migrated. Since a wallet may have only one active migration, any signed-in user could open one for someone else's wallet id and lock its real signers out of migrating until they cancelled it; the CONFLICT message also told them who holds an existing migration. getMigrationByOriginalWallet returned the active migration (initiator address, migration plan) to any session at all. - createMigration: the initiating address itself must be a signer or the owner of the original wallet (not just any address in a multi-wallet session). - getMigrationByOriginalWallet: caller must have access to the wallet; it stays wallet-scoped, not owner-scoped, so co-signers still see a migration another signer started. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017rkSXFrvazW5oPKicrnTyY
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This branch was successfully deployed
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.
What
Two
migrationtRPC procedures did not check that the caller belongs to the wallet being migrated:createMigrationchecked that the session controlsownerAddress, but not thatownerAddressbelongs tooriginalWalletId. A wallet may have only one active migration (pending/in_progress), so any signed-in user could open one for someone else's wallet id. The real signers were then locked out of migrating, and only the stranger could cancel. TheCONFLICTmessage also told a stranger who holds an existing migration.getMigrationByOriginalWalletreturned the active migration (initiator address,migrationData) to any session at all.Change
createMigration: the initiating address itself must be a signer or the owner of the original wallet. This is checked inline rather than withassertWalletAccess, because that helper also accepts any other address in a multi-wallet session, and the lock would then be recorded under a non-signer address.getMigrationByOriginalWallet:assertWalletAccesson the wallet. The query stays wallet-scoped, not owner-scoped, so co-signers still see a migration another signer started (the "already in progress" notice inmigrate-wallet.tsx).Legitimate flows are unchanged. The migrate page only renders after
wallet.getWallet, which already requires the session address to be a signer.Tests
src/__tests__/trpc/migrationAuth.test.ts(10 tests, mock DB): stranger refused and no lock created; existing initiator not leaked; unknown wallet →NOT_FOUND; signer can create; mismatchedownerAddressrefused before any wallet lookup; multi-wallet session can't record a non-signer initiator; anonymous / stranger reads refused before the migration is read; co-signer sees another signer's migration;nullwhen none is active.npx tsc --noEmit✅jest -c jest.trpc.config.mjs --runInBand): 17 suites / 138 tests passednode scripts/run-tests.mjs: CJS 185 suites / 2352 passed (2 skipped), ESM 13 / 140 passednext build --webpack+check-bundle-budget --report: within budget. This is a server-only change, so bundles are unchanged.Not covered / follow-ups (need a decision)
updateMigrationStep/updateMigrationData/cancelMigration/completeMigration/getMigrationcheck onlymigration.ownerAddress. They do not re-check wallet membership (for example, an initiator later removed as a signer).updateMigrationStepalso accepts anynewWalletIdunchecked. Both are left out to keep this PR small.findFirst+createwith no unique constraint, so it is racy. Fixing it needs a schema migration, so it is out of scope here.Generated by Claude Code