T09 · Insecure Skill Coding Practices
- Location
scripts/hire.js:50- Finding
Escrow Payment Is Released Without Validating Provider Output
- Content
View full analysis
setTimeout(r, 3000)); const cNonce = await wallet.getNonce("pending"); const confirmTx = await escrow.confirmComplete(jobId, { nonce: cNonce }); await confirmTx.wait(); console.log("Payment released!"); await new Promise(r => setTimeout(r, 3000)); const rNonce = await wallet.getNonce("pending"); const rateTx = await escrow.rateJob(jobId, 5, { nonce: rNonce }); await rateTx.wait(); console.log("Rated 5/5 stars."); } catch (e) { console.log("Auto-completed by provider."); } } else { console.log("\nJob completed!"); } // Parse result try { const r = JSON.parse(result); if (r.success) { console.log(`\nResult: Swapped ${r.amountIn} ${r.fromToken} → ${r.amountOut} ${r.toToken}`); console.log(`TX Hash: ${r.txHash}`); if (r.basescanUrl) console.log(`Verify: ${r.basescanUrl}`); console.log(`DEX: ${r.dex}`); } else { console.log(`\nJob failed: ${r.error}`); } } catch { console.log(`\nResult: ${result}`); } process.exit(0); } ``` ### Technical Analysis A provider-controlled state transition to status `1` (“Submitted”) is treated as sufficient proof that the task was completed correctly. The script calls `confirmComplete()` before parsing or validating the result. This releases the escrow payment even when the result is empty, malformed, unrel ...[truncated 1699 chars]- Remediation
View remediation
