T09 · Insecure Skill Coding Practices
- Location
scripts/pipeline.ts:77- Finding
API-Controlled Pipeline Transactions Are Signed Without Binding Them to User Confirmation
- Content
View full analysis
{ const result = PipelineRunAndWaitInputSchema.safeParse(args); if (!result.success) { return result.error.errors.map((e) => `${e.path.join('.')}: ${e.message}`).join('; '); } return null; }, run: async (args) => { const input = PipelineRunAndWaitInputSchema.parse(args); return runPipelineAndWait(input); }, }, ``` ```ts // scripts/pipeline.ts:77-83 if (task.status === 'sign_pending') { // Task needs signing - use evm_tx_data from API const rawTxData = task.evm_tx_data || task.tx_data; if (params.mode === 'external_signer') { ``` ```ts // scripts/pipeline.ts:101-118 const txData = mapTransactionData(rawTxData); const walletClient = getTradeWalletClient(); // Broadcast transaction const txHash = await walletClient.sendTransaction({ to: txData.to as `0x${string}`, data: txData.data as `0x${string}`, value: txData.value ? BigInt(txData.value) : undefined, gas: txData.gas ? BigInt(txData.gas) : undefined, maxFeePerGas: txData.maxFeePerGas ? BigInt(txData.maxFeePerGas) : undefined, maxPriorityFeePerGas: txData.maxPriorityFeePerGas ? BigInt(txData.maxPriorityFeePerGas) : undefined, }); logger.info({ task_id: task.task_id, tx_hash: txHash }, 'Transaction broadcast'); txHashes.push(txHash); ``` ```ts // scripts/util.ts:86-123 export function mapTransactionData(raw: unknown): TransactionData { if (!raw || typeof raw !== 'object') { throw new Error('Invalid transaction data: expected object'); } const data = raw as Record; if (!data.to || typeof data. ...[truncated 3995 chars]- Remediation
View remediation
