T09 · Insecure Skill Coding Practices
Error
- Location
- polymarket-trade.js:291
- Finding
- Automatic Trading Logic Executes Unhedged Speculative Orders Instead of Arbitrage<![CDATA[ ## Vulnerability Details **File Location**: `polymarket-trade.js:291-295` **Vulnerability Type**: Unsafe financial transaction logic **Risk Level**: High ### Vulnerable Code ```js if (op.yesPrice < 0.5) { await placeOrder(op.yesToken, 'BUY', op.yesPrice, 10); } else if (op.noPrice < 0.5) { await placeOrder(op.noToken, 'BUY', op.noPrice, 10); } ``` ### Technical Analysis The documentation describes an arbitrage strategy in which both complementary outcomes are purchased when their combined cost is below the guaranteed settlement value. The implementation does not perform that strategy. It purchases only one outcome based on whether its displayed price is below `0.5`. A single-outcome purchase remains fully exposed to the event result and is therefore directional speculation rather than arbitrage. In addition, `detectArbitrage()` uses the absolute deviation from one: ```js const deviation = Math.abs(1 - total); ``` Consequently, the code treats both underpricing and overpricing as opportunities without determining whether a profitable pair of executable orders exists. The displayed prices may also be stale indicative values rather than executable order-book prices. The code does not account for liquidity, fees, slippage, partial fills, or whether the complementary order can be executed. Because `scan` and `start` automatically invoke `placeOrder()` whenever a wallet is configured, real wallet funds can be committed without per-order confirmation. ### Attack Path 1. A user configures `POLYMARKET_PRIVATE_KEY` for a funded Polygon wallet. 2. The user invokes `arbitrage scan` or `arbitrage start`, relying on the documented claim that the Skill performs arbitrage. 3. The Skill identifies a market whose Yes and No prices deviate from one by more than 2%. 4. The Skill selects only one outcome priced below `0.5`. 5. It submits a real GTC buy order for that single outcome. 6. If the selected outcome loses, or if market conditions move adversely, t ...[truncated 1159 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not automatically trade based on indicative outcome prices alone. 2. Confirm that the combined executable ask prices satisfy: - `yesAsk + noAsk + fees + expectedSlippage < guaranteedPayout`. 3. Query current order books and validate sufficient depth for the complete intended size. 4. Purchase both complementary outcomes as one coordinated strategy. If atomic execution is unavailable, implement strict handling for partial fills and immediately cancel or hedge unmatched exposure. 5. Reject opportunities where the combined price exceeds one; do not use absolute deviation as the profitability test. 6. Calculate exchange fees, blockchain costs, tick sizes, minimum order sizes, and settlement constraints before submitting an order. 7. Introduce configurable limits for order size, aggregate exposure, orders per interval, daily loss, and total wallet allocation. 8. Make dry-run mode the default and require explicit opt-in for real trading. 9. Require clear user confirmation before the first real order and display the exact maximum financial exposure. 10. Add automated tests proving that both legs are executed only when the net guaranteed return remains positive under conservative fee and slippage assumptions. ]]>
