T09 · Insecure Skill Coding Practices
Error
- Location
- trader.py:52
- Finding
- Cached live trading client can bypass subsequent paper-mode requests<![CDATA[ ## Vulnerability Details **File Location**: `trader.py:52-81` **Vulnerability Type**: Unsafe global client state and execution-mode confusion **Risk Level**: High ### Vulnerable Code ```python def get_client(live: bool = False) -> SimmerClient: global _client, MAX_POSITION, MIN_VOLUME, MAX_SPREAD, MIN_DAYS, MAX_POSITIONS global YES_THRESHOLD, NO_THRESHOLD, MIN_TRADE, MIN_VIOLATION if _client is None: venue = "polymarket" if live else "sim" _client = SimmerClient( api_key=os.environ["SIMMER_API_KEY"], venue=venue, ) if live: _client.live = True try: _client.apply_skill_config(SKILL_SLUG) except AttributeError: pass # apply_skill_config only available in Simmer runtime MAX_POSITION = float(os.environ.get("SIMMER_MAX_POSITION", str(MAX_POSITION))) MIN_VOLUME = float(os.environ.get("SIMMER_MIN_VOLUME", str(MIN_VOLUME))) MAX_SPREAD = float(os.environ.get("SIMMER_MAX_SPREAD", str(MAX_SPREAD))) MIN_DAYS = int(os.environ.get( "SIMMER_MIN_DAYS", str(MIN_DAYS))) MAX_POSITIONS = int(os.environ.get( "SIMMER_MAX_POSITIONS", str(MAX_POSITIONS))) YES_THRESHOLD = float(os.environ.get("SIMMER_YES_THRESHOLD", str(YES_THRESHOLD))) NO_THRESHOLD = float(os.environ.get("SIMMER_NO_THRESHOLD", str(NO_THRESHOLD))) MIN_TRADE = float(os.environ.get("SIMMER_MIN_TRADE", str(MIN_TRADE))) MIN_VIOLATION = float(os.environ.get("SIMMER_MIN_VIOLATION", str(MIN_VIOLATION))) return _client ``` ### Technical Analysis The module stores a single `SimmerClient` in the global `_client` variable. The requested `live` mode is used only when that client is first created. Later calls return the existing client without confirming that its venue and live-trading state match the new request. If a long-lived Python process first i ...[truncated 1506 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Remove the process-global singleton and create an explicitly configured client for each run. - Alternatively, cache clients separately by immutable venue, such as `{"sim": sim_client, "polymarket": live_client}`. - Before every trade, verify that the client's effective venue and live flag exactly match the current run's requested mode. - Fail closed if the SDK does not expose a verifiable execution mode. - Pass the expected mode directly into the execution function instead of relying on mutable module state. - Add regression tests that invoke live and simulation runs in both orders within the same process and assert that no live trade can occur during a simulation request. ]]>
