Back to skill

Security audit

Polymarket Science Milestones Trader

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed trading bot, but its live-trading safeguards have concrete gaps that could cause unintended financial exposure.

Review carefully before installing or running live. Use a restricted Simmer/Polymarket credential, keep balances and per-trade limits low, avoid long-lived/imported use until the client cache bug is fixed, and require the publisher to pin simmer-sdk and enforce SIMMER_MIN_VOLUME before any live order.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (3)

T08 · Insecure Dependencies

Warning
Location
clawhub.json:6
Finding

Unpinned Trading SDK Creates a Supply-Chain Risk

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:84
Finding

Configured Minimum-Volume Trading Safeguard Is Not Enforced

Content
View full analysis
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 execution loop at `trader.py:348-379` also submits trades without checking market volume: ```python markets = find_markets(client) print(f"[polymarket-science-milestones-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.trade( market_id=m.id, side=side, amount=size, source=TRADE_SOURCE, skill_slug=SKILL_SLUG, reasoning=reasoning, ) ``` ### Technical Analysis `SIMMER_MIN_VOLUME` is represented in the documentation and configuration as a minimum market-volume filter, but the value is only pars ...[truncated 1583 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
trader.py:52
Finding

Global Client Cache Can Retain Live Trading Mode During a Later Paper Run

Content
View full analysis
SimmerClient: """ live=False → venue="sim" (paper trades — safe default). live=True → venue="polymarket" (real trades, only with --live flag). """ global _client, MAX_POSITION, MIN_VOLUME, MAX_SPREAD, MIN_DAYS, MAX_POSITIONS, YES_THRESHOLD, NO_THRESHOLD, MIN_TRADE if _client is None: venue = "polymarket" if live else "sim" _client = SimmerClient( api_key=os.environ["SIMMER_API_KEY"], venue=venue, ) # Load tunable overrides set via the Simmer UI (SIMMER_* vars only). if live: _client.live = True try: _client.apply_skill_config(SKILL_SLUG) except AttributeError: pass # apply_skill_config only available in Simmer runtime # Re-read params in case apply_skill_config updated os.environ. 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))) return _client ``` The displayed mode is based on the requested argument rather than the cached client's effective venue at `trader.py:342-349`: ```python def run(live: bo ...[truncated 2334 chars]
Remediation
View remediation
SimmerClient: venue = "polymarket" if live else "sim" if venue not in _clients: _clients[venue] = SimmerClient( api_key=os.environ["SIMMER_API_KEY"], venue=venue, ) client = _clients[venue] if live and getattr(client, "venue", venue) != "polymarket": raise RuntimeError("Live client venue mismatch") if not live and getattr(client, "venue", venue) != "sim": raise RuntimeError("Paper client venue mismatch") return client ``` ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (2)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill explicitly requires a high-value environment credential (SIMMER_API_KEY) but does not declare any permissions or allowed-tools scope to constrain environment access. That creates an overbroad trust boundary: if the runtime exposes environment variables generally, the skill could access more secrets than intended, and users reviewing the manifest have no explicit least-privilege declaration to validate.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This manifest requires the SIMMER_API_KEY environment variable, which indicates the skill accesses a sensitive credential. In this file there is no accompanying disclosure or warning explaining that the skill will read and use that credential, which fits the missing user warning criterion for user-visible skill descriptions/metadata.

Content

No source excerpt is available for this finding.