Back to skill

Security audit

Polymarket Bundle Crypto Fade Trader

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed trading bot, but its live-trading safeguards and dependency controls do not fully match the authority it requests.

Review this carefully before installing for live use. Keep it in paper mode unless you have verified the YES/NO trade semantics, pinned and reviewed simmer-sdk, enforced real account-wide position and volume limits, and restricted SIMMER_API_KEY with the smallest possible trading scope and spend limits.

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)

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:24
Finding

Declared 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. Fades strong directional moves: - After strong-UP streak -> expect mean reversion DOWN -> buy NO if p >= NO_THRESHOLD (i.e. the next interval is still priced Up, so we fade it) - After strong-DOWN streak -> expect mean reversion UP -> buy YES if p <= YES_THRESHOLD (i.e. the next interval is still priced Down, so we fade it) """ 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 if days < MIN_DAYS: return None, 0, f"Only {days} days to resolve" except Exception: pass ``` ### Technical Analysis The project declares `SIMMER_MIN_VOLUME` as a risk parameter and documents it as a minimum market-volume filter. However, neither market discovery nor signal validation reads a market's volume or compares it with `MIN_VOLUME`. Consequently, the configured control has no effect. A matching market may progress to trade execution based only on probability, spread, resol ...[truncated 1378 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:310
Finding

Maximum Open-Position Limit Only Counts Orders in the Current Run

Content
View full analysis
= MAX_POSITIONS: break side, size, reasoning = compute_signal(m, fade_dir, streak_len) 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 The configuration describes `SIMMER_MAX_POSITIONS` as the maximum number of concurrent open positions. The implementation instead initializes `placed` to zero every time `run` executes and increments it only for successful orders during that process invocation. The program does not: - Query existing open positions - Account for positions created by prior executions - Account for positions created by another concurrent process - Reserve capacity atomically before placing an order - Prevent duplicate exposure to the same market Therefore, the control is a per-run order-count limit rather than a concurrent-position limit. Repeated or overlapping executions can exceed the advertised exposure boundary. ### Attack Path 1. The account already has one or more open positions from a previous run. 2. The trader is executed again manually or through an ex ...[truncated 1030 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Error
Location
clawhub.json:6
Finding

Privileged Trading SDK Dependency Is Unpinned

Content
View full analysis
Remediation
View remediation
" ] ``` 2. Use a lockfile with cryptographic hashes where supported, such as a hash-locked requirements file generated by `pip-tools`. 3. Verify the package's publisher, source repository, release signatures, and build provenance before upgrading. 4. Review dependency changes before accepting new versions and use automated vulnerability scanning. 5. Run the trader under a dedicated, unprivileged operating-system account or isolated container. 6. Provide only the environment variables strictly required by the trader. 7. Restrict `SIMMER_API_KEY` using least-privilege controls, including venue restrictions, transaction limits, and withdrawal prohibition where supported. 8. Rotate the API key if dependency compromise is suspected. 9. Consider placing transaction limits in a trusted server-side control so a compromised client library cannot bypass them. ]]>
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • 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
91% confidence
Finding

The skill declares access to sensitive environment data via required credentials but does not define any explicit tool scope or permissions boundary. In an agent ecosystem, this weakens least-privilege guarantees and can allow a skill with trading authority credentials to access or misuse secrets or broader capabilities than intended.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation says a strong-up streak should mean-revert down, but the stated action is 'sell NO'. In Polymarket up-or-down markets, selling NO is economically equivalent to taking the UP side, which aligns with continuation rather than a downward fade. This is an active contradiction in the skill's own intent documentation.

Content

No source excerpt is available for this finding.