T09 · Insecure Skill Coding Practices
- Location
validate.js:116- Finding
Remote API Can Supply an Unbounded Collateral Amount Through Incomplete Local Validation
- Content
View full analysis
Vulnerability Details
File Location:
validate.js, lines 116–169
Vulnerability Type: Insufficient validation of remotely constructed financial transactions
Risk Level: MediumVulnerable Code
javascript const call3Spender = '0x' + call3.data.slice(34, 74).toLowerCase(); const call3Amount = BigInt('0x' + call3.data.slice(74, 138)); if (call3Spender !== ALLOWLIST.aavePool && call3Spender !== ALLOWLIST.morphoVault) { throw new Error(`Validation failed: Call 3 spender (${call3Spender}) is not an approved yield pool`); } // Reject infinite / unlimited approvals const maxUint = BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'); if (call3Amount === maxUint) { throw new Error(`Validation failed: Unlimited approval is strictly rejected`); } // --- Call 4: Supply Collateral to Yield Pool --- const call4 = calls[3]; const poolTarget = norm(call4.to); if (poolTarget !== ALLOWLIST.aavePool && poolTarget !== ALLOWLIST.morphoVault) { throw new Error(`Validation failed: Call 4 target (${poolTarget}) is not an approved yield pool`); } // Enforce Call 3 approved spender strictly equals Call 4 destination if (call3Spender !== poolTarget) { throw new Error(`Validation failed: Call 3 spender (${call3Spender}) does not match Call 4 target (${poolTarget})`); } // Validate Call 4 calldata based on protocol if (poolTarget === ALLOWLIST.aavePool) { if (!call4.data.startsWith(ALLOWLIST.selectors.aaveSupply)) { throw new Error(`Validation failed: Call 4 does not use Aave V3 supply selector (${ALLOWLIST.selectors.aaveSupply})`); } const asset = '0x' + call4.data.slice(34, 74).toLowerCase(); const supplyAmount = BigInt('0x' + call4.data.slice(74, 138)); const onBehalfOf = '0x' + call4.data.slice(162, 202).toLowerCase(); if (asset !== ALLOWLIST.usdc) { throw new Error(`Validation failed: Aave supply asset is not USDC (${asset})`); } if ...[truncated 4188 chars]- Remediation
View remediation
Remediation Suggestions
- Require an explicit, locally approved collateral amount as an input to
validatePaymentBatch. - Compare that amount exactly against both
call3Amountand the decoded AavesupplyAmountor MorphodepositAmount. - If collateral is derived from a multiplier and buffer, calculate it locally from user-approved values rather than trusting fields returned by the hosted API.
- Enforce a locally configured absolute maximum collateral amount and reject zero, negative, malformed, non-finite, or out-of-range payment parameters before conversion.
- Generate the confirmation summary exclusively from decoded, validated calldata. Do not use
buildResponse.summaryas the authoritative source for transaction amounts. - Present the decoded payment, fee, approval, collateral deposit, beneficiary, and target protocol to the user or policy layer before signing.
- Add tests in which the remote summary reports a normal collateral amount while calldata contains a larger amount, and verify that validation rejects the batch.
- Consider requiring a cryptographically bound user authorization object containing the payment amount, maximum collateral, recipient, sender, protocol, and chain ID.
- Require an explicit, locally approved collateral amount as an input to
