T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/apex.mjs:190
- Finding
- Signed trading operations accept unvalidated order sizes and prices<![CDATA[ ## Vulnerability Details **File Location**: `scripts/apex.mjs:190-243` and `scripts/apex.mjs:246-283` **Vulnerability Type**: Insufficient validation of security-critical financial inputs **Risk Level**: High ### Vulnerable Code ```js case 'market-buy': case 'market-sell': { const apexClient = await createPrivateClient(); const symbol = normalizeSymbol(args[1]); const size = args[2]; if (!symbol || !size) { throw new Error(`Usage: apex ${command} <coin> <size>`); } const side = command === 'market-buy' ? 'BUY' : 'SELL'; const symbolInfo = apexClient.symbols?.[symbol]; if (!symbolInfo?.l2PairId) { throw new Error(`Unknown symbol: ${symbol}`); } let price = ''; try { const worst = await apexClient.privateApi.getWorstPrice(symbol, size, side); price = worst?.worstPrice || ''; } catch (err) { const ticker = await getTickerPrice(apexClient, symbol); price = ticker?.lastPrice || ''; } if (!price) throw new Error(`Unable to determine price for ${symbol}`); const makerFeeRate = apexClient.account?.contractAccount?.makerFeeRate || '0'; const takerFeeRate = apexClient.account?.contractAccount?.takerFeeRate || '0'; const limitFee = calculateLimitFee(price, size, takerFeeRate, symbolInfo.baseCoinRealPrecision); const order = { pairId: symbolInfo.l2PairId, makerFeeRate, takerFeeRate, symbol, side, type: 'MARKET', size: String(size), price: String(price), limitFee, reduceOnly: false, timeInForce: 'IMMEDIATE_OR_CANCEL', expiration: Math.floor(Date.now() / 1000 + 30 * 24 * 60 * 60), }; const result = await apexClient.privateApi.createOrder(order); console.log(JSON.stringify(result, null, 2)); break; } ``` The limit-order path uses the same insufficient validation pattern: ```js case 'limit-buy': case 'limit-sell': { const apexClient = await createPrivateClient(); const symbol = normalizeSymbol(args[1]); const size = args[2]; const price ...[truncated 3194 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse all monetary inputs with `BigNumber` before creating a private client or signing an order. 2. Reject values that are non-numeric, non-finite, zero, or negative. 3. Enforce the exchange-provided minimum quantity, maximum quantity, quantity step, price tick, and decimal-precision constraints. 4. Calculate order notional and compare it with available balance and total equity. 5. Reject or require additional explicit approval for trades exceeding a configured percentage of account equity. 6. Compare limit prices with a fresh market price and reject or reconfirm excessive deviations. 7. Add a maximum configurable order-notional limit that defaults to a conservative value. 8. Require an explicit, short-lived confirmation token containing the symbol, side, size, price, environment, and estimated notional. 9. Add tests covering negative numbers, zero, `NaN`, `Infinity`, exponential notation, excessive precision, oversized values, and malformed strings. 10. Treat downstream SDK and exchange validation as defense in depth rather than the primary validation mechanism. ]]>
