T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:157
- Finding
- Untrusted Firebase Game State Controls On-Chain Wager Settlement<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:157-170` and `SKILL.md:423-425` **Vulnerability Type**: Untrusted off-chain state used to authorize an on-chain financial transaction **Risk Level**: High ### Vulnerable Code The documented game-completion process stores the result in Firebase and passes a caller-supplied winner address to the contract: ```json { "game_state": "finished", "winner": "blue", "end_reason": "checkmate" } ``` ```text endGame(bytes6 inviteCode, address winnerAddress) ``` The example agent automatically trusts the Firebase state and submits the associated settlement transaction: ```javascript if (state.game_state === 'finished') { chessContract.endGame(game.invite_code, state.winner); } ``` ### Technical Analysis The prescribed implementation treats mutable Firebase fields as authoritative evidence for settling an on-chain wager. The documentation does not describe any server-side authorization, signed move history, player consensus, authenticated adjudication, or on-chain validation that proves the declared winner is legitimate. Client-side move validation using `chess.js` does not establish a trustworthy settlement boundary. A participant capable of modifying the relevant Firebase game record may publish a fabricated terminal state or winner. The example event listener then uses that attacker-influenced value to initiate a financial transaction without independently reconstructing and validating the game or requiring explicit user approval. There is also a type inconsistency in the documented flow: Firebase represents the winner as a color such as `"blue"`, while `endGame` expects an address. Implementations may attempt to resolve this field through other mutable Firebase properties, introducing an additional opportunity for address substitution. The actual loss depends on the deployed contract's access controls and winner-validation logic, which were not included in the project. However, the Skill e ...[truncated 1672 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Do not automatically settle from mutable Firebase fields.** Treat `game_state`, `winner`, player addresses, and move history as untrusted input. Never pass these values directly into a financial transaction. 2. **Require cryptographic settlement authorization.** Use EIP-712 typed settlement messages signed by both players. The signed payload should bind the chain ID, contract address, invite code, both player addresses, final position, result, and a unique nonce. 3. **Enforce critical invariants on-chain.** The contract should verify that: - The supplied winner is one of the registered players. - The caller is authorized. - The game is active and has not already been settled. - The settlement signatures correspond to the registered players and exact game. - Nonces and game identifiers prevent replay across games, contracts, or chains. 4. **Use an authenticated adjudication mechanism for disputes.** If both players do not agree, settlement should require a trusted adjudicator, an optimistic dispute window with fraud proofs, or on-chain verification of a complete signed move transcript. 5. **Sign every move.** Each move should include the invite code, ply number, prior-state hash, move, resulting-state hash, and player signature. Before settlement, replay the complete sequence with a deterministic chess rules engine and verify every signature and state transition. 6. **Harden Firebase access controls.** Configure Firebase Security Rules so only the registered player whose turn it is may submit the next move. Prevent clients from directly changing player identities, terminal status, winner fields, wager metadata, or prior move-history entries. Use transactions or compare-and-set semantics to prevent concurrent state overwrites. 7. **Resolve winner identities from trusted contract state.** Do not accept an arbitrary address from Firebase. After validating the result, map the winning col ...[truncated 772 chars]
