T09 · Insecure Skill Coding Practices
Warning
- Location
- trader.py:93
- Finding
- Declared Minimum-Volume Safeguard Is Not Enforced<![CDATA[ ## Vulnerability Details **File Location**: `trader.py:30`, `trader.py:93-102`, and trade flow at `trader.py:387-415` **Vulnerability Type**: Missing risk-control enforcement **Risk Level**: Medium ### Vulnerable Code ```python MIN_VOLUME = float(os.environ.get("SIMMER_MIN_VOLUME", "5000")) ``` ```python def find_markets(client: SimmerClient) -> list: """Find active markets matching strategy keywords, deduplicated.""" seen, unique = set(), [] for kw in KEYWORDS: try: for m in client.find_markets(query=kw): if m.id not in seen: seen.add(m.id) unique.append(m) except Exception as e: print(f"[search] {kw!r}: {e}") return unique ``` The resulting markets are subsequently passed to `compute_signal()` and then to `client.trade()` without a volume check. ### Technical Analysis `SIMMER_MIN_VOLUME` is documented as a minimum market-volume filter and is loaded into `MIN_VOLUME`. However, `find_markets()` only filters duplicate market IDs. Neither this function nor the later signal and execution flow compares a market's volume against `MIN_VOLUME`. Consequently, the configured safeguard has no effect. This is particularly relevant to live prediction-market trading because low-volume markets can have unreliable prices, shallow order books, poor execution, and greater susceptibility to price manipulation. The issue also creates a discrepancy between the documented security posture and actual behavior: operators may reasonably believe that markets below the configured volume threshold cannot be traded. ### Attack Path 1. An attacker creates or identifies a low-volume Polymarket market containing one of the monitored catastrophe-related keywords. 2. The market is returned by `client.find_markets()`. 3. `find_markets()` accepts it because it checks only whether the market ID has already been seen. 4. If its displayed probability, spread, and resolu ...[truncated 822 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Retrieve the market's authoritative volume field and reject markets below the threshold before signal computation: ```python def find_markets(client: SimmerClient) -> list: seen, unique = set(), [] for kw in KEYWORDS: try: for market in client.find_markets(query=kw): if market.id in seen: continue volume = getattr(market, "volume", None) if volume is None: print(f" [skip] {market.id}: volume unavailable") continue try: volume = float(volume) except (TypeError, ValueError): print(f" [skip] {market.id}: invalid volume") continue if volume < MIN_VOLUME: continue seen.add(market.id) unique.append(market) except Exception as e: print(f"[search] {kw!r}: {e}") return unique ``` 2. Fail closed when volume is missing, malformed, negative, stale, or supplied in an unexpected unit. 3. Confirm the exact volume attribute and units exposed by the pinned SDK version. 4. Repeat the check immediately before live execution if market metadata can change between discovery and trading. 5. Add tests for volume below, equal to, and above `MIN_VOLUME`, as well as missing and malformed values. ]]>
