Back to skill

Security audit

Polymarket Energy Transition Trader

Security checks for vulnerabilities and agentic risk

Overview

This skill is disclosed as a Polymarket trading tool, but its live-trading safeguards can fail open and may exceed configured financial limits.

Review before installing, especially if you intend to use --live. Use a narrowly funded and scoped Simmer/Polymarket credential, keep the skill in paper mode until the fail-open checks and trade-size validation are fixed, and pin or review the simmer-sdk dependency before trusting it with live trading authority.

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:3
Finding

Unpinned Trading SDK Creates a Supply-Chain Risk

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
trader.py:257
Finding

Live Trading Safeguards Are Incomplete and Fail Open

Content
View full analysis
MAX_SPREAD: return None, 0, f"Spread {market.spread_cents/100:.1%} > {MAX_SPREAD:.1%}" # Days-to-resolution gate if market.resolves_at: try: resolves = datetime.fromisoformat(market.resolves_at.replace("Z", "+00:00")) days = (resolves - datetime.now(timezone.utc)).days if days < MIN_DAYS: return None, 0, f"Only {days} days to resolve" except Exception: pass ``` The context and slippage check at `trader.py:285-309` returns approval after an SDK or API failure: ```python def context_ok(client: SimmerClient, market_id: str) -> tuple[bool, str]: """Check flip-flop and slippage safeguards.""" try: ctx = client.get_market_context(market_id) if not ctx: return True, "no context" if ctx.get("discipline", {}).get("is_flip_flop"): reason = ctx["discipline"].get("flip_flop_reason", "recent reversal") return False, f"Flip-flop: {reason}" slip = ctx.get("slippage", {}) if isinstance(slip, dict) and slip.get("slippage_pct", 0) > 0.15: return False, f"Slippage {slip['slippage_pct']:.1%}" for w in ctx.get("warnings", []): print(f" [warn] {w}") except Exception as e: print(f" [ctx] {market_id}: {e}") return True, "ok" ``` The execution loop limits orders placed during the current invocation, but it does not retrieve or count existing open positions: ```python placed = 0 for m in markets: if placed >= MAX_POSITIONS: break ...[truncated 2871 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
trader.py:271
Finding

Minimum Trade Floor Can Exceed the Configured Maximum Position

Content
View full analysis
= NO_THRESHOLD: conviction = min(1.0, (p - NO_THRESHOLD) / (1 - NO_THRESHOLD) * bias) size = max(MIN_TRADE, round(conviction * MAX_POSITION, 2)) edge = p - NO_THRESHOLD return "no", size, f"NO YES={p:.0%} edge={edge:.0%} bias={bias:.2f}x size=${size} — {q[:65]}" ``` The metadata allows the maximum position to be configured as low as 1 USD: ```json { "env": "SIMMER_MAX_POSITION", "default": 25, "range": [ 1, 200 ], "step": 1, "label": "Max position size (USD)" } ``` At the same time, the minimum trade can be configured as high as 100 USD: ```json { "env": "SIMMER_MIN_TRADE", "type": "number", "default": 5, "range": [ 1, 100 ], "step": 1, "label": "Min trade size (USD)" } ``` ### Technical Analysis The formula uses: ```python max(MIN_TRADE, calculated_size) ``` This guarantees a minimum order value but does not guarantee that the resulting value is less than or equal to `MAX_POSITION`. The metadata permits configurations where `MIN_TRADE > MAX_POSITION`. For example: - `SIMMER_MAX_POSITION=1` - `SIMMER_MIN_TRADE=100` For a qualifying signal, the expression returns 100, even though the configured maximum position is 1. This contradicts the source-code documentation stating that the result is capped so the ...[truncated 1398 chars]
Remediation
View remediation
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (2)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill references environment-based credentials (SIMMER_API_KEY) and describes live trading capability, but it does not declare an explicit tool/permission scope such as allowed environment access. In an agent ecosystem, missing scope boundaries can let the skill access sensitive secrets more broadly than intended and increases the chance of unauthorized credential use or accidental exposure.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The invocation text is broad and matches generic investing intent, which can cause the agent to auto-select this skill in situations where the user did not explicitly ask for speculative trading. Because this skill can ultimately place live trades when run with a flag and uses high-value credentials, over-broad routing increases the risk of inappropriate activation and financially consequential actions.

Content

No source excerpt is available for this finding.