You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Replace simple wallet lookup with cryptographic proof-of-membership verification
Difficulty: Expert Type: Security
Background:app/api/verify/route.ts's live-mode path calls client.verifyWallet(discordUserId, wallet), which — based on IntegrationClient's contract — presumably performs a lookup-style verification (does this Discord user's claimed wallet exist and hold a valid membership?) rather than a cryptographic proof that the requester actually controls the claimed wallet.
Problem: A lookup-style verification is vulnerable to a user simply claiming someone else's public wallet address (all Ethereum addresses are public) to fraudulently gain access to that wallet's associated roles/passes, since nothing in the flow proves the requester — not just the address — controls the private key.
Expected outcome:/api/verify (and the underlying IntegrationClient.verifyWallet contract) is upgraded to a genuine challenge-response cryptographic proof: the server issues a single-use nonce/challenge, the client signs it with the claimed wallet's private key (e.g. via the same wallet-connection flow as #38's SIWE work), and only a valid signature over that specific challenge is accepted as proof of control — closing the address-spoofing gap.
Suggested implementation:
Add a nonce-issuance step to the verification flow (reusable with feat: implement production-ready webhook verification utilities #38's SIWE nonce infrastructure if implemented, or standalone otherwise), tied to the specific (discordUserId, wallet) pair being verified to prevent cross-context replay.
Update /api/verify/route.ts to require and cryptographically verify a signature over the issued challenge (using viem's signature verification utilities) before calling through to IntegrationClient/recording a verified membership.
Update the Discord bot's verification command flow (wherever it currently prompts a user to submit a wallet) to guide the user through signing the challenge, not just pasting an address.
Ensure nonces are single-use, scoped, and time-limited, with replay attempts explicitly rejected and logged.
Acceptance criteria:
A verification request with a claimed wallet but no valid signature over the issued challenge is rejected.
A verification request with a valid signature over the correct challenge for that (discordUserId, wallet) pair succeeds.
A replayed or cross-context signature (valid for a different challenge or different Discord user) is rejected.
verify.test.ts/live-verify.test.ts are extended to cover unsigned, wrongly-signed, and replayed-signature scenarios.
Replace simple wallet lookup with cryptographic proof-of-membership verification
Difficulty: Expert
Type: Security
Background:
app/api/verify/route.ts's live-mode path callsclient.verifyWallet(discordUserId, wallet), which — based onIntegrationClient's contract — presumably performs a lookup-style verification (does this Discord user's claimed wallet exist and hold a valid membership?) rather than a cryptographic proof that the requester actually controls the claimed wallet.Problem: A lookup-style verification is vulnerable to a user simply claiming someone else's public wallet address (all Ethereum addresses are public) to fraudulently gain access to that wallet's associated roles/passes, since nothing in the flow proves the requester — not just the address — controls the private key.
Expected outcome:
/api/verify(and the underlyingIntegrationClient.verifyWalletcontract) is upgraded to a genuine challenge-response cryptographic proof: the server issues a single-use nonce/challenge, the client signs it with the claimed wallet's private key (e.g. via the same wallet-connection flow as #38's SIWE work), and only a valid signature over that specific challenge is accepted as proof of control — closing the address-spoofing gap.Suggested implementation:
(discordUserId, wallet)pair being verified to prevent cross-context replay./api/verify/route.tsto require and cryptographically verify a signature over the issued challenge (usingviem's signature verification utilities) before calling through toIntegrationClient/recording a verified membership.Acceptance criteria:
(discordUserId, wallet)pair succeeds.verify.test.ts/live-verify.test.tsare extended to cover unsigned, wrongly-signed, and replayed-signature scenarios.Likely affected files:
apps/dashboard/app/api/verify/route.ts,packages/integration-client/src/client.ts,apps/discord-bot/src/index.ts,apps/dashboard/test/verify.test.tsLabels:
security,feature,help wanted,priority: high,GrantFox OSS,Maybe Rewarded,Official Campaign | FWC26