T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/create-token.ts:114
- Finding
- Untrusted Server-Provided Transaction Is Signed Without Validation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/create-token.ts:114-155` **Vulnerability Type**: Signing and broadcasting an untrusted transaction without validating its instructions **Risk Level**: High ### Vulnerable Code ```ts const res = await fetch(API_URL, { method: 'POST', body: formData, }); if (!res.ok) { const text = await res.text().catch(() => ''); throw new Error(`API request failed: ${res.status} ${res.statusText}\n${text}`); } const json = await res.json() as { data: { transaction: string; signature: string; dbc_config: string; dbc_pool: string; base_mint: string; name: string; symbol: string; uri: string; royalty_party: string; }; common: Record<string, unknown>; }; const { transaction: txBase58, dbc_config, dbc_pool, base_mint, uri } = json.data; if (!txBase58) { throw new Error('API returned empty transaction. Response: ' + JSON.stringify(json)); } console.error(` base_mint: ${base_mint}`); console.error(` dbc_config: ${dbc_config}`); console.error(` dbc_pool: ${dbc_pool}`); console.error(` uri: ${uri}`); // ── Step 2: Deserialize and sign transaction ────────────────────────── const txBytes = bs58.decode(txBase58); const tx = VersionedTransaction.deserialize(txBytes); tx.sign([keypair]); // ── Step 3: Send to Solana RPC ──────────────────────────────────────── console.error('Sending transaction ...'); const txHash = await connection.sendRawTransaction(tx.serialize(), { skipPreflight: false, maxRetries: 3, }); ``` ### Technical Analysis The remote API at `https://gate.game.com/v3/hotfun/agent/create_pool_with_config` fully controls the serialized Solana transaction returned to the client. The script decodes and deserializes that transaction, signs it with the wallet key supplied through `PRIVATE_KEY`, and broadcasts it without inspecting its contents. The script does not verify: - The transaction fee payer. - The invoked Solana program IDs. - The transactio ...[truncated 2023 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Decode and validate every transaction instruction before signing. 2. Require the fee payer to equal the expected wallet public key. 3. Maintain a strict allowlist of permitted Solana program IDs and instruction variants. 4. Reject unrelated writable accounts, additional signers, unexpected transfers, account closures, authority changes, and token approvals. 5. Enforce explicit upper limits for network fees, service fees, SOL transfers, and token transfers. 6. Resolve and validate all address lookup tables referenced by versioned transactions. 7. Verify that returned mint, pool, and configuration accounts match the transaction instructions and API response. 8. Simulate the transaction and inspect expected SOL and token balance changes. 9. Present a human-readable transaction summary to the user and require explicit confirmation immediately before signing. 10. Prefer constructing the transaction locally from audited instructions rather than signing an opaque transaction supplied by a remote service. 11. Treat API response fields as untrusted and validate their schema, types, addresses, and relationship to the requested operation. ]]>
