Resolve Unauthenticated Minting, Predictable Randomness, and Missing Rate Limits in three-card-monte - #138
Open
magqqgq wants to merge 1 commit into
Open
Resolve Unauthenticated Minting, Predictable Randomness, and Missing Rate Limits in three-card-monte#138magqqgq wants to merge 1 commit into
three-card-monte#138magqqgq wants to merge 1 commit into
Conversation
…Rate Limits in `three-card-monte` ### Description This pull request addresses findings F-03, F-11, F-12, and F-13 from the workspace security audit[cite: 30]. It completely overhauls the game logic to make rounds server-authoritative, prevents unauthorized on-chain reward minting, introduces proper rate-limiting for gas-spending endpoints, and hardens the random number generation logic against state recovery attacks. ### Key Changes & Remediations #### 1. Server-Authoritative Reward Minting (F-03) * **Closing the Minting Oracle:** The `/api/win` endpoint previously accepted unsigned, unverified win claims directly from the client request body and minted rewards unconditionally[cite: 30]. This has been refactored to rely on a server-side Redis validation flow. * **Secure State Initialization:** A new route, `/api/game/start`, securely selects the winning card using `crypto.randomInt` and stores it in Redis under an unguessable 128-bit `gameId`[cite: 30]. The winning card is deliberately excluded from the client response[cite: 30]. * **Atomic Single-Use Gate:** The `claimRound` logic uses a `SET NX EX` atomic lock to prevent concurrent replay race conditions, ensuring a round can only ever be consumed once[cite: 30]. #### 2. Rate Limiting for Gas & Signer Endpoints (F-11) * **Sliding-Window Implementation:** A new in-memory rate limiter (`lib/rate-limit.ts`) has been introduced to protect the application's budget[cite: 30]. The game start endpoint is capped at 20 requests/min, while the payout endpoint is restricted to 10 requests/min. * **Safe Cache Pruning:** The rate-limit cache pruning defers deletions to avoid ES5 `TS2802` `Map` iteration mutation errors[cite: 30]. #### 3. Cryptographically Secure Randomness (F-12) * **CSPRNG Implementation:** Replaced the vulnerable `Math.random()` (which relies on `xorshift128+` and is susceptible to state recovery and modulo bias) with `crypto.getRandomValues()` paired with explicit rejection sampling (`lib/shuffle.ts`)[cite: 30]. #### 4. Error Masking (F-13) * **Information Leakage Prevented:** The `app/api/win/route.ts` previously returned raw `error.message` strings from CDP and RPC internals back to the caller[cite: 30]. All upstream errors are now logged strictly server-side and resolved to the client via generic `502 Bad Gateway` or `400 Bad Request` responses[cite: 30].
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.
Description
This pull request addresses findings F-03, F-11, F-12, and F-13 from the workspace security audit[cite: 30]. It completely overhauls the game logic to make rounds server-authoritative, prevents unauthorized on-chain reward minting, introduces proper rate-limiting for gas-spending endpoints, and hardens the random number generation logic against state recovery attacks.
Key Changes & Remediations
1. Server-Authoritative Reward Minting (F-03)
/api/winendpoint previously accepted unsigned, unverified win claims directly from the client request body and minted rewards unconditionally[cite: 30]. This has been refactored to rely on a server-side Redis validation flow./api/game/start, securely selects the winning card usingcrypto.randomIntand stores it in Redis under an unguessable 128-bitgameId[cite: 30]. The winning card is deliberately excluded from the client response[cite: 30].claimRoundlogic uses aSET NX EXatomic lock to prevent concurrent replay race conditions, ensuring a round can only ever be consumed once[cite: 30].2. Rate Limiting for Gas & Signer Endpoints (F-11)
lib/rate-limit.ts) has been introduced to protect the application's budget[cite: 30]. The game start endpoint is capped at 20 requests/min, while the payout endpoint is restricted to 10 requests/min.TS2802Mapiteration mutation errors[cite: 30].3. Cryptographically Secure Randomness (F-12)
Math.random()(which relies onxorshift128+and is susceptible to state recovery and modulo bias) withcrypto.getRandomValues()paired with explicit rejection sampling (lib/shuffle.ts)[cite: 30].4. Error Masking (F-13)
app/api/win/route.tspreviously returned rawerror.messagestrings from CDP and RPC internals back to the caller[cite: 30]. All upstream errors are now logged strictly server-side and resolved to the client via generic502 Bad Gatewayor400 Bad Requestresponses[cite: 30].