Back to skill

Security audit

Polymarket 24h Sports Line Curve Trader

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed trading skill, but its live-trading safeguards do not fully enforce the limits it advertises.

Review carefully before installing, especially before using --live. Use paper mode first, supply the least-privileged or sandbox trading key available, and do not rely on the advertised position-count, minimum-volume, or context-risk safeguards until they are fixed or enforced server-side.

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

T09 · Insecure Skill Coding Practices

Error
Location
trader.py:432
Finding

Configured Concurrent Position Limit Is Not Enforced Across Runs

Content
View full analysis
= MAX_POSITIONS: break market = opp[0] side, size, reasoning = compute_signal(market, opp) if not side: safe_print(f" [skip] {reasoning}") continue ok, why = context_ok(client, market_id) if not ok: safe_print(f" [skip] {why}") continue try: r = client.trade( market_id=market_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[:110]}") if r.success: placed += 1 ``` ### Technical Analysis The `MAX_POSITIONS` setting is documented as the maximum number of concurrent open positions. The implementation does not query existing account positions or outstanding orders. Instead, it initializes `placed` to zero for every invocation and only increments it when an order succeeds during that invocation. Consequently, the limit is an order-count limit for one process run rather than an account-wide concurrent-position limit. Repeated manual or automated executions can each submit up to `MAX_POSITIONS` additional orders. The check is also not atomic with order placement. If multiple instances execute concurrently, every instance maintains its own counter and can independently consume the full configured allowance. ### Attack Path 1. The skill is configured with `SIMMER_MAX_POSITIONS=8`. 2. A live invocation finds eight qualifying opportunities and successful ...[truncated 852 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:35
Finding

Documented Minimum Market Volume Control Is Never Applied

Content
View full analysis
list: """Find active sports O/U markets, deduplicated. Filters out non-sport markets (crypto, finance, etc.).""" seen: set[str] = set() unique: list = [] for kw in KEYWORDS: try: for m in client.find_markets(query=kw): market_id = getattr(m, "id", None) if market_id and market_id not in seen: q = getattr(m, "question", "") if is_sport_market(q): seen.add(market_id) unique.append(m) except Exception as e: safe_print(f"[search] {kw!r}: {e}") return unique ``` ### Technical Analysis `SIMMER_MIN_VOLUME` is exposed as a tunable and documented as the minimum acceptable market volume. Although its value is parsed and refreshed by `get_client`, it is never referenced by `find_markets`, `build_curves`, `valid_market`, or the order-execution loop. A low-volume market can therefore enter a curve and generate a trade as long as it passes the unrelated probability, spread, resolution-time, and context checks. A displayed spread alone does not replace a volume or depth control: a thin market may have little executable liquidity, be easy to manipulate, or be difficult to exit. This discrepancy creates a false assurance that the configured minimum-volume policy protects live execution. ### Attack Path 1. A low-volume sports O/U market is returned by a configured keyword search. 2. Its question passes `is_sport_market`. 3. The market is added to a curve ...[truncated 792 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
trader.py:357
Finding

Trading Continues When Risk-Context Validation Fails

Content
View full analysis
tuple: """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", []): safe_print(f" [warn] {w}") except Exception as e: safe_print(f" [ctx] {market_id}: {e}") return True, "ok" ``` ### Technical Analysis The function is intended to block trades when recent behavior indicates a flip-flop or estimated slippage exceeds 15%. It returns approval when: - `get_market_context` returns no context; - the context request raises an exception; - the returned object has an unexpected structure that triggers an exception; or - malformed slippage data prevents the intended comparison. This is fail-open behavior for a financial risk control. Temporary service failure, SDK incompatibility, malformed API responses, or network disruption can therefore disable the safeguards without preventing live order execution. Warnings are only printed and do not influence the decision. ### Attack Path 1. A candidate market passes the initial signal and market checks. 2. `get_market_context` fails because of a network error, service outage, rate limit, SDK error, or malformed response. 3. The exception is caught and logged. 4. `context_ok` returns `(True, "ok")`. 5. The execution loop interprets ...[truncated 690 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
clawhub.json:5
Finding

Security-Sensitive Trading SDK Is Installed Without a Version or Integrity Pin

Content
View full analysis
Remediation
View remediation
" ] ``` 2. Use a lock file with cryptographic hashes or an installation mechanism equivalent to `pip --require-hashes`. 3. Record and verify hashes for all transitive dependencies, not only the direct SDK. 4. Review release notes and source changes before updating the pin. 5. Install packages only from an explicitly trusted index and use protections against dependency confusion. 6. Run the skill with a minimally scoped trading credential and server-side spending or venue restrictions. 7. Isolate the process so the dependency cannot access unrelated secrets or sensitive files. 8. Add automated dependency vulnerability and provenance scanning to the release process. ]]>
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 declares access to a high-value environment credential (SIMMER_API_KEY) but does not define any explicit tool scope such as permissions or allowed-tools. That creates an over-broad trust boundary: an agent running the skill may be able to access environment data without a clearly constrained capability declaration, increasing the chance of unintended secret exposure or misuse if the skill is modified, composed with other skills, or run in a permissive host.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest explicitly requires a sensitive API key for an automated trading skill, but the file provides no user-facing warning about credential handling, external API usage, or the fact that the skill can place trades. In a trading context this omission is materially risky because users may supply live credentials without understanding scope, storage expectations, or financial consequences.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.