T09 · Insecure Skill Coding Practices
- Location
scripts/compound.ts:198- Finding
Untrusted Odos API Transactions Are Signed Without Sufficient Validation
- Content
View full analysis
{ const response = await rateLimitedFetch('https://api.odos.xyz/sor/assemble', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ userAddr: userAddress, pathId, simulate: false, }), }); if (!response.ok) { console.log(` ⚠️ Odos assemble failed: ${response.status}`); return null; } const data = await response.json() as OdosAssembleResponse; if (!data.transaction?.to || !data.transaction?.data) { console.log(` ⚠️ Invalid Odos assemble response`); return null; } return data; } ``` ```ts const assembled = await assembleOdosTransaction(quote.pathId, account.address); if (!assembled) { console.log(` ⚠️ Could not assemble transaction, skipping ${token.symbol}\n`); continue; } const gasEstimate = BigInt(assembled.transaction.gas); const gasWithBuffer = gasEstimate + (gasEstimate * 50n / 100n); const nonce = await getFreshNonce(publicClient, account.address); const swapHash = await walletClient.sendTransaction({ to: assembled.transaction.to as Address, data: assembled.transaction.data as Hex, value: BigInt(assembled.transaction.value), gas: gasWithBuffer, nonce, }); ``` ### Technical Analysis The Odos assembly API controls the transaction destination, calldata, native token value, and gas estimate. Validation only verifies that the `to` and `data` properties exist. The implementation does not: - Require `transaction.to` to equal the known `ODOS_ROUTER`. - Decode and validate the returned calldata. - Verify the input token, input amount, output token, recip ...[truncated 1499 chars]- Remediation
View remediation
