T09 · Insecure Skill Coding Practices
- Location
index.js:60- Finding
Unsafe and Non-Canonical Transaction Amount Parsing
- Content
View full analysis
Vulnerability Details
File Location:
index.js, lines 60-69 and 104-116
Vulnerability Type: Improper input validation and unsafe numeric conversion
Risk Level: HighVulnerable Code
javascript async function sendSOL(recipientAddress, lamports) { const recipient = new PublicKey(recipientAddress); const sender = keypair.publicKey; const transaction = new Transaction().add( SystemProgram.transfer({ fromPubkey: sender, toPubkey: recipient, lamports: parseInt(lamports), }) );javascript // Send tokens const signature = await transfer( connection, keypair, senderTokenAccount.address, recipientTokenAccount.address, keypair, parseInt(amount) // assumes amount is in smallest unit (lamports for USDC, etc) );Technical Analysis
Both transaction functions convert payment amounts with
parseIntwithout first validating that the complete input is a canonical positive integer. This conversion is permissive: an input such as1000000abcis interpreted as1000000, while decimal values are silently truncated.The code also converts amounts to JavaScript
numbervalues without enforcing theNumber.MAX_SAFE_INTEGERboundary. Large integer strings can therefore lose precision before transaction construction. No explicit minimum, maximum, balance-based policy, per-transaction limit, or confirmation control is enforced.This issue affects both the command-line interface and the exported programmatic API. Any Agent workflow that supplies amounts derived from untrusted quotes, messages, or generated content may authorize a value different from the exact value supplied by the caller.
Attack Path
- An attacker or untrusted Agent response supplies a crafted payment amount to a workflow using this Skill.
- The workflow passes the value to
sendSOL,sendSPLToken,send-sol, orsend-tokenwithout independent validat ...[truncated 777 chars]
- Remediation
View remediation
Remediation Suggestions
- Accept amounts only as digit-only strings or
bigintvalues. - Reject empty, signed, decimal, exponential, hexadecimal, trailing-character, zero, and negative values.
- Avoid conversion to JavaScript
numberwhen the Solana API supportsbigint. - If a number is unavoidable, require
Number.isSafeInteger(value)andvalue > 0. - Define explicit per-transaction and daily transfer limits.
- Verify that the requested amount and expected fees are within the wallet balance.
- Require an independent recipient-and-amount approval step before signing high-value transactions.
- Use a validation pattern such as:
javascript function parsePositiveAmount(value) { const text = String(value); if (!/^[0-9]+$/.test(text)) { throw new TypeError('Amount must be a positive integer in smallest units'); } const amount = BigInt(text); if (amount <= 0n) { throw new RangeError('Amount must be greater than zero'); } return amount; }- Accept amounts only as digit-only strings or
