T09 · Insecure Skill Coding Practices
- Location
scripts/transfer.mjs:21- Finding
Insufficient Validation of Financial Transfer Amount
- Content
View full analysis
Vulnerability Details
File Location:
scripts/transfer.mjs, lines 21–25 and 45–50
Vulnerability Type: Improper input validation and unsafe numeric parsing
Risk Level: MediumVulnerable Code
js if (!args.to || !args.amount) { console.error('Usage: node transfer.mjs --to <recipient> --amount <number> [--memo "reason"]'); process.exit(1); }js body: JSON.stringify({ to: args.to, amount: parseFloat(args.amount), memo: args.memo, }),Technical Analysis
The transfer script verifies only that
--amountis present. It then usesparseFloat()without checking whether the entire input is a valid decimal number or whether the parsed value is finite, positive, within an acceptable range, and compatible with the token's supported precision.JavaScript's
parseFloat()accepts numeric prefixes. For example,10abcis silently converted to10. Inputs such as0, negative numbers, extremely large values, and values that produce non-finite results are not rejected locally. AlthoughJSON.stringify()converts non-finite numeric values tonull, the resulting malformed request is still submitted to the financial API.Correct server-side validation may prevent an invalid transaction, but the client should not rely exclusively on undocumented remote safeguards for a value-changing operation.
Attack Path
- A user, automation workflow, or calling Agent invokes the script with a crafted or accidentally malformed value, such as
--amount 10abc,--amount -10, or an excessively large number. - The presence check succeeds because the argument is a non-empty string.
parseFloat()coerces the input without requiring full-string validity.- The resulting value is placed in the JSON request body.
- The script sends the request to the authenticated transfer endpoint.
- If the service accepts the coerced or insufficiently constrained value, an unint ...[truncated 855 chars]
- A user, automation workflow, or calling Agent invokes the script with a crafted or accidentally malformed value, such as
- Remediation
View remediation
Remediation Suggestions
- Validate the complete amount string against the token's canonical decimal syntax rather than accepting a numeric prefix.
- Convert the value once and reject it unless
Number.isFinite(amount)is true. - Require the amount to be strictly greater than zero.
- Enforce documented minimum and maximum transfer limits.
- Enforce the token's supported decimal precision, preferably by converting decimal input to an integer quantity in the smallest token unit rather than relying on binary floating-point arithmetic.
- Reject exponential notation unless the API explicitly supports it.
- Consider requiring explicit user confirmation that displays the normalized recipient, amount, agent ID, and memo before submitting the transfer.
- Preserve server-side validation as a separate mandatory control.
Example hardening pattern:
js const amountText = args.amount; if (!/^(?:0|[1-9]\d*)(?:\.\d{1,SUPPORTED_PRECISION})?$/.test(amountText)) { console.error('Amount must be a valid positive decimal with supported precision.'); process.exit(1); } const amount = Number(amountText); if (!Number.isFinite(amount) || amount <= 0 || amount > MAX_TRANSFER) { console.error('Amount is outside the permitted transfer range.'); process.exit(1); }Replace
SUPPORTED_PRECISIONandMAX_TRANSFERwith limits defined by the Quack Network API.
