T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:210
- Finding
- Blind Signing of Remote Server-Supplied Solana Transactions<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:210-233` **Vulnerability Type**: Unvalidated transaction signing **Risk Level**: High ### Vulnerable Code ```typescript async function executeAction(prepareUrl: string, submitUrl: string, body: object, keypair: Keypair) { const authHeaders = createAuthHeaders(keypair); // Step 1: Prepare (requires auth) const prepRes = await fetch(prepareUrl, { method: 'POST', headers: { ...authHeaders }, body: JSON.stringify(body), }); const { data } = await prepRes.json(); // Step 2: Sign const tx = Transaction.from(Buffer.from(data.transaction, 'base64')); tx.sign(keypair); // Step 3: Submit const submitRes = await fetch(submitUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ signedTransaction: tx.serialize().toString('base64'), }), }); return await submitRes.json(); } ``` ### Technical Analysis The function obtains a serialized transaction from a remote `prepareUrl`, deserializes it, and signs it with the wallet keypair without validating the transaction contents. No checks ensure that: - Every instruction invokes the documented ChronoBets program ID. - Token instructions use the documented Solana mainnet USDC mint. - Writable and signer accounts match the requested operation. - Token and SOL transfer destinations are expected. - Transfer amounts, platform fees, creator fees, and stakes match the user's request. - The market identifier and outcome correspond to the requested action. - The transaction contains no additional or unrelated instructions. - The transaction has been simulated successfully. - The user has approved the exact financial consequences. Base64 decoding is not local code or shell execution, so the pre-scan's decode-and-execute indicator does not represent arbitrary code execution. Nevertheless, signing an untrusted serialized blockchain transaction authorizes the instructions embedd ...[truncated 1907 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Implement a fail-closed transaction-verification layer before signing: 1. **Restrict API destinations** - Do not accept arbitrary `prepareUrl` and `submitUrl` values. - Construct URLs from a fixed, allowlisted HTTPS origin. - Reject redirects to other origins. 2. **Allowlist programs** - Require ChronoBets instructions to target the documented program ID: `8Lut48u2M5eFjnebP1KowRKytAFDHKvFA11UPR2Y3dD4`. - Permit System Program, Compute Budget, Associated Token Account, and SPL Token instructions only where specifically required. - Reject every unknown program or unexpected instruction. 3. **Validate instruction semantics** - Decode each ChronoBets instruction and verify its discriminator and arguments. - Confirm the market ID, outcome, stake, bet amount, and minimum shares against the original request. - Verify all signer and writable accounts. - Recompute and verify expected PDAs. 4. **Validate financial effects** - Require the documented USDC mint: `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`. - Check token source accounts, destination accounts, treasury, creator, and vault addresses. - Reject transfers exceeding the user-approved amount and fee tolerance. - Reject authority changes, delegate approvals, account closures, and unrelated SOL transfers. 5. **Simulate before signing** - Simulate the transaction using a trusted Solana RPC endpoint. - Compare pre- and post-transaction token balances. - Abort on unexpected logs, programs, account mutations, or balance changes. 6. **Require explicit approval** - Present the exact asset, amount, fees, recipients, market, outcome, and maximum loss. - Require explicit user confirmation for every real-money transaction. - Never autonomously create markets, bet, or challenge outcomes without a user-defined spending policy. 7. **Use wallet isolation** - Use a dedicated low-balance wallet rather than a general-pu ...[truncated 78 chars]
