T09 · Insecure Skill Coding Practices
- Location
trader.py:199- Finding
Documented liquidity and portfolio exposure safeguards are not enforced
- Content
View full analysis
Vulnerability Details
File Location:
trader.py:24-32,trader.py:199-235
Vulnerability Type: Missing financial risk-control enforcement
Risk Level: MediumThe skill declares a minimum market-volume requirement and describes
MAX_POSITIONSas a limit on concurrent open positions. However, the trading loop never checks market volume, whileMAX_POSITIONSonly limits successful orders during the current invocation.Relevant configuration code (
trader.py:24-32):python # Risk parameters — declared as tunables in clawhub.json, tunable from Simmer UI. # Named SIMMER_* so apply_skill_config() can load automaton-managed overrides. MAX_POSITION = float(os.environ.get("SIMMER_MAX_POSITION", "25")) MIN_VOLUME = float(os.environ.get("SIMMER_MIN_VOLUME", "2000")) MAX_SPREAD = float(os.environ.get("SIMMER_MAX_SPREAD", "0.15")) MIN_DAYS = int(os.environ.get( "SIMMER_MIN_DAYS", "14")) MAX_POSITIONS = int(os.environ.get( "SIMMER_MAX_POSITIONS", "8")) # Signal thresholds — buy YES below YES_THRESHOLD, sell NO above NO_THRESHOLD.Trading loop (
trader.py:199-235):python def run(live: bool = False) -> None: mode = "LIVE" if live else "PAPER (sim)" print(f"[polymarket-emerging-tech-trader] mode={mode} max_pos=${MAX_POSITION} min_vol=${MIN_VOLUME} max_spread={MAX_SPREAD:.0%} min_days={MIN_DAYS}") client = get_client(live=live) markets = find_markets(client) print(f"[polymarket-emerging-tech-trader] {len(markets)} candidate markets") placed = 0 for m in markets: if placed >= MAX_POSITIONS: break side, size, reasoning = compute_signal(m) if not side: print(f" [skip] {reasoning}") continue ok, why = context_ok(client, m.id) if not ok: print(f" [skip] {why}") continue try: r = client.tra ...[truncated 2394 chars]- Remediation
View remediation
Remediation Suggestions
- Validate market volume before signal generation or order submission:
python volume = getattr(m, "volume", None) if volume is None: print(" [skip] Market volume unavailable") continue if volume < MIN_VOLUME: print(f" [skip] Volume ${volume:.2f} below ${MIN_VOLUME:.2f}") continue - Confirm the SDK's authoritative volume field and units rather than assuming an attribute name.
- Query current open positions before trading and calculate available position slots from the account's actual state.
- Count newly opened positions together with existing positions, rather than counting only successful orders in the current process.
- Fail closed if account-position or liquidity information cannot be retrieved.
- Add tests covering low-volume markets, pre-existing positions, repeated invocations, and unavailable risk data.
- Update documentation if
MAX_POSITIONSis intentionally meant to be only a per-run order limit.
- Validate market volume before signal generation or order submission:
