T09 · Insecure Skill Coding Practices
Warning
- Location
- trader.py:347
- Finding
- Declared market-volume and portfolio-exposure safeguards are not enforced<![CDATA[ ## Vulnerability Details **File Location**: `trader.py:29-30, 347-415` and `clawhub.json:36-47, 75-86` **Vulnerability Type**: Missing enforcement of configured risk controls **Risk Level**: Medium The project declares `SIMMER_MIN_VOLUME` as a minimum market-volume filter and `SIMMER_MAX_POSITIONS` as a maximum concurrent open-position limit. However, the trading flow never checks market volume, and `MAX_POSITIONS` only limits successful orders placed during the current process invocation. ### Complete Code Snippet Configuration values are loaded in `trader.py`: ```python MIN_VOLUME = float(os.environ.get("SIMMER_MIN_VOLUME", "3000")) MAX_POSITIONS = int(os.environ.get( "SIMMER_MAX_POSITIONS", "8")) ``` The configuration describes these values as market-volume and open-position safeguards: ```json { "env": "SIMMER_MIN_VOLUME", "type": "number", "default": 3000, "range": [ 0, 500000 ], "step": 1000, "label": "Min market volume (USD)" } ``` ```json { "env": "SIMMER_MAX_POSITIONS", "type": "number", "default": 8, "range": [ 1, 20 ], "step": 1, "label": "Max open positions" } ``` The live order loop only counts orders successfully placed during the current run: ```python placed = 0 for date_str, spike_time, spike_dir, spike_count, spike_coins in spikes: if placed >= MAX_POSITIONS: break # Find the next 5-min window (spike_time + 5 minutes) next_time = spike_time + 5 next_key = (date_str, next_time) next_window = by_window.get(next_key, {}) if not next_window: safe_print( f" [{date_str} {spike_time//60}:{spike_time%60:02d}] " f"no next window at +5min" ) continue # Find coins in the next window that haven't caught up for coin, m in next_window.items(): if placed >= MAX_POSITIONS: break p = float(m.current_probability) # Check if this coin is lagging (not ye ...[truncated 4017 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Retrieve authoritative market-volume data before signal evaluation and reject markets whose volume is unavailable or below `MIN_VOLUME`. 2. Query current open positions and pending orders from the trading venue before placing any order. 3. Calculate remaining capacity using account-wide state, for example: `remaining = MAX_POSITIONS - existing_open_positions - pending_open_orders`. 4. Stop trading when `remaining <= 0`, and decrement the remaining capacity only after verifying the resulting account state. 5. Consider enforcing a maximum total USDC exposure in addition to a position-count limit. 6. Fail closed in live mode if volume, portfolio, or pending-order data cannot be retrieved. 7. Prevent overlapping scheduler executions with a process lock or an account-level atomic reservation mechanism. 8. Rename the setting if it is intentionally a per-run order limit; otherwise, update the implementation so that it matches the documented “Max open positions” behavior. 9. Add tests covering pre-existing positions, repeated invocations, pending orders, missing volume data, and below-threshold markets. ]]>
