Back to skill

Security audit

Polymarket Ladder Chess Tournament Trader

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed paper-by-default trading bot, but its live-trading path has material safety-control gaps that users should review before installation.

Review this before enabling live mode. Paper mode is the default, but live mode can place real USDC trades using SIMMER_API_KEY. Pin and review simmer-sdk, use a limited trading credential if possible, and do not rely on the documented volume and open-position safeguards until they are fixed and tested.

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

Security-Critical Trading Dependency Is Not Version-Pinned

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:49
Finding

Configured Minimum-Volume Trading Safeguard Is Never Enforced

Content
View full analysis
= MAX_POSITIONS: break side, size, reasoning = compute_signal(m, violation_pct, sum_total, direction) 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[:75]}") if r.success: placed += 1 ``` ### Technical Analysis `SIMMER_MIN_VOLUME` is documented as the minimum market-volume filter and is loaded into `MIN_VOLUME`. Nevertheless, no condition in `find_markets`, `compute_signal`, or the execution loop compares a market's volume against this value. As a result, the configured safeguard has no effect. A market can progress from discovery to signal generation and trade execution regardless of its trading volume. This is especially material for an automated strategy because thin markets can be more susceptible to price manipulation, large effective spreads, unstable quotes, and limited exit liquidity. The existing spread and context checks do not replace a volume gate. A thin market may temporarily report an a ...[truncated 1499 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:255
Finding

Maximum Concurrent Position Limit Only Counts Orders From the Current Run

Content
View full analysis
= MAX_POSITIONS: break ``` The counter increases only after a successful order in the current process: ```python if r.success: placed += 1 ``` The configured limit is described as follows: ```json { "env": "SIMMER_MAX_POSITIONS", "type": "number", "default": 10, "range": [ 1, 20 ], "step": 1, "label": "Max open positions" } ``` ### Technical Analysis The configuration and documentation describe `SIMMER_MAX_POSITIONS` as a maximum number of concurrent open positions. The implementation instead limits only the number of successful orders placed during one execution of `run`. No portfolio or open-order API is queried before `placed` is initialized. Existing positions, pending orders, and positions created by earlier invocations are therefore not counted. Restarting or scheduling the process resets the counter to zero even while earlier positions remain open. The counter also represents successful order responses rather than confirmed distinct open positions. It does not account for multiple orders affecting the same market, partial fills, closed positions, or pending orders. ### Attack Path 1. The account already has one or more open positions from an earlier run. 2. The trader starts again while those positions remain open. 3. `placed` is reset to zero because it is a local variable initialized on every invocation. 4. Existing positions and pending orders are not requested from the trading service. 5. The application places as many as `MAX_POSITIONS` additional successful orders. 6 ...[truncated 823 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
79% confidence
Finding

The skill references a high-value credential (SIMMER_API_KEY) and describes trading behavior, but it does not declare an explicit tool/permission scope such as allowed tools or environment access. That creates an authorization ambiguity: an agent runtime may grant broader environment access than intended, increasing the chance that sensitive variables are exposed or misused by this skill or by future modifications.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This manifest declares a required environment variable named SIMMER_API_KEY, indicating the skill depends on a sensitive credential. In this manifest file there is no accompanying disclosure or warning explaining that the skill will use an API key for trading-related operations, which is relevant to user privacy and account safety.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.