Back to skill

Security audit

Polymarket Candle Gap Fill Trader

Security checks for vulnerabilities and agentic risk

Overview

The skill is transparent about automated Polymarket trading and defaults to paper mode, but its live-trading safeguards are incomplete enough to require review before use.

Review this before installing for live use. It is not evidence of theft or hidden execution, and paper mode is the default, but do not run it with --live or a funded trading credential unless you accept that liquidity and total exposure limits may be weaker than documented. Pin and review simmer-sdk, restrict the SIMMER_API_KEY to the smallest possible balance and permissions, and add or verify server-side/account-wide risk limits before real trading.

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

Unpinned Third-Party Trading Dependency

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:195
Finding

Configured Minimum-Volume Safeguard Is Not Enforced

Content
View full analysis
tuple[str | None, float, str]: """ Returns (side, size, reasoning) or (None, 0, skip_reason). Conviction-based sizing per CLAUDE.md. Fills gaps between consecutive intervals: - fill_up: current is DOWN outlier after prior UP -> buy YES (revert upward) - fill_down: current is UP outlier after prior DOWN -> buy NO (revert downward) """ p = market.current_probability q = getattr(market, "question", "") # Spread gate if market.spread_cents is not None and market.spread_cents / 100 > 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 ``` `MIN_VOLUME` is read from configuration but is never used by market discovery, signal validation, context validation, or order execution. This contradicts the documented behavior that describes it as a minimum market-volume filter. ### Technical Analysis Market volume is an important liquidity and manipulation-resistance control. Without enforcing the configured threshold, an otherwise matching market can proceed to `client.trade(...)` regardless of how little trading activity it has. The existing spread check is not an equivalent safeguard. A low-volume market can temporarily display an ...[truncated 1401 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:312
Finding

Maximum Position Limit Counts Only Orders Placed During the Current Run

Content
View full analysis
= MAX_POSITIONS: break side, size, reasoning = compute_signal(m, gap_dir, gap_mag) if not side: safe_print(f" [skip] {reasoning}") continue ok, why = context_ok(client, m.id) if not ok: safe_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, ) tag = "(sim)" if r.simulated else "(live)" status = "OK" if r.success else f"FAIL:{r.error}" safe_print(f" [trade] {side.upper()} ${size} {tag} {status} -- {reasoning[:70]}") if r.success: placed += 1 except Exception as e: safe_print(f" [error] {m.id}: {e}") ``` ### Technical Analysis `MAX_POSITIONS` is documented and labeled as the maximum number of concurrent open positions. The implementation instead initializes `placed` to zero on every invocation and increments it only for successful orders submitted during that invocation. The code does not retrieve existing open positions or pending orders. It also lacks synchronization across overlapping processes. As a result, the condition limits orders per process run rather than total concurrent exposure. For example, with `MAX_POSITIONS=10`, an account that already has ten open positions can submit up to ten additional successful orders during another invocation. Two concurrent invocations can each independently observe `placed == 0` and submit their own allocation. ### Attack Path 1. The account already contains open positions from an earlier execution. 2. The Skill runs again, eith ...[truncated 971 chars]
Remediation
View remediation
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
90% confidence
Finding

The skill references a high-value environment credential (SIMMER_API_KEY) but does not declare any explicit tool scope or permissions boundary. Even though the file is mostly documentation, an undeclared environment capability weakens least-privilege guarantees and could allow a future implementation or agent runtime to access secrets more broadly than intended.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The manifest clearly declares automated trading behavior and requires an API key, but it does not present any user-facing warning, consent gate, or safety notice about placing market orders or handling credentials. In a trading skill, this omission increases the risk that a user enables the agent without understanding that it can autonomously execute real market actions with supplied secrets.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.