Back to skill

Security audit

Polymarket Copy Size Conviction Trader

Security checks for vulnerabilities and agentic risk

Overview

This skill is openly a copy-trading tool, but its live-trading safeguards can fail open and its sensitive trading dependency is not pinned.

Review this before installing if you may ever run it with --live. Keep paper mode unless you understand the trading risk, use a tightly scoped SIMMER_API_KEY with server-side spending and position limits, and prefer a version that pins simmer-sdk and fails closed when portfolio state cannot be verified.

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 (2)

T08 · Insecure Dependencies

Warning
Location
clawhub.json:3
Finding

Unpinned Third-Party Trading SDK Creates a Supply-Chain Risk

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
trader.py:371
Finding

Live-Trading Position-Limit Safeguard Fails Open on Portfolio Lookup Errors

Content
View full analysis
bool: """Check portfolio context to prevent excessive positions.""" try: positions = client.get_positions() open_count = len([p for p in positions if float(getattr(p, "size", 0)) > 0]) if open_count >= MAX_POSITIONS: safe_print(f" [GATE] Already at {open_count}/{MAX_POSITIONS} positions, skipping") return False except Exception as exc: safe_print(f" [WARN] Could not check positions: {exc}") return True ``` ### Technical Analysis `context_ok()` is intended to prevent trading when the portfolio already contains `MAX_POSITIONS` open positions. However, every exception from `client.get_positions()`, response iteration, attribute conversion, or position-size parsing is caught and ignored. Execution then reaches `return True`, authorizing subsequent trades without establishing the current portfolio state. This is a fail-open security and financial-risk control. The behavior contradicts the documented claim that `context_ok()` prevents exceeding the maximum number of open positions. The run loop separately limits the number of successful trades during the current invocation, but that counter starts at zero and does not account for existing positions. Therefore, failure of the portfolio lookup can allow the invocation to add as many as `MAX_POSITIONS` further trades even when the account is already at or above its configured portfolio limit. ### Attack Path 1. The Skill is invoked with `--live`, enabling real Polymarket trades. 2. The account already has positions, potentially at or above `MAX_POSITIONS`. 3. `client.get_positions()` fails because of an API outage, timeout, malformed response, SDK defect, authentication issue, or deliberately disrupted resp ...[truncated 1456 chars]
Remediation
View remediation
bool: try: positions = client.get_positions() if positions is None: raise ValueError("Position response is missing") open_count = sum( 1 for position in positions if float(getattr(position, "size", 0)) > 0 ) return open_count < MAX_POSITIONS except (ValueError, TypeError, AttributeError, OSError) as exc: safe_print(f" [GATE] Could not validate positions: {exc}") return not live ``` 2. Pass the execution mode explicitly to the guard and permit fail-open behavior, if desired, only for paper trading. 3. Replace the broad `Exception` handler with expected exception types while treating unexpected failures as fatal. 4. Validate the SDK response schema before counting positions. 5. Calculate the remaining capacity as `MAX_POSITIONS - open_count` and stop the trade loop when that capacity is exhausted. 6. Recheck the position count immediately before each live order to reduce race conditions and concurrent-run exposure. 7. Enforce position-count and spending limits server-side so local client failures cannot bypass them. 8. Prevent overlapping live invocations with an account-level lock or idempotency mechanism. ]]>
Vulnerability Patterns
  • 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
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (1)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill describes behavior that inherently requires network access and use of environment-provided secrets (SIMMER_API_KEY), but it does not declare any explicit tool scope such as permissions or allowed-tools. That creates an authorization gap: an agent runtime may grant broader-than-intended access, making it easier for the skill to reach arbitrary external services or access sensitive environment data beyond what is necessary for leaderboard and trading API interactions.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.