T09 · Insecure Skill Coding Practices
- Location
index.js:136- Finding
Caller-Supplied Transaction Claims Can Falsely Settle Payments
- Content
View full analysis
JSON.parse(line)); const quote = quotes.find(q => q.id === payment.quote_id); if (quote) { quote.status = 'settled'; quote.settled_at = new Date().toISOString(); } // Write back const updatedPayments = payments.map(p => (p.id === payment_id ? payment : p)); writeFileSync( PAYMENTS_DB, updatedPayments.map(p => JSON.stringify(p)).join('\n') + '\n' ); ``` ### Technical Analysis `recordPayment()` trusts the caller-provided `confirmed` flag and transaction hash. It does not query a Solana RPC endpoint or validate that the supplied signature identifies a real, finalized transaction. The implementation does not verify: - Whether the signature exists on Solana. - Whether the transaction completed successfully and reached the required finality. - Whether the payer and recipient match the payment record. - Whether the transferred amount matches `amount_lamports`. - Whether the transaction transfers native SOL rather than another asset. - Whether the same transaction was previously used for another payment. In addition, the associated quote is unconditionally marked `settled` whenever it is found. This happens even if `confirmed` is explicitly set to `false`, because quote settlement is not conditional on the resulting payment status. ### Attack Path 1. An attacker obtains or creates a valid pending payment identifier. 2. The attacker invokes: ```javascript recordPayment({ payment_id: 'p_validPaymentId', tx_hash: 'arbitrary-or-unrelated-signature', confirmed: true, }); ``` 3. The function records the payment ...[truncated 875 chars]- Remediation
View remediation
