Back to skill

Security audit

Polymarket Twitter Bin Decay Trader

Security checks for vulnerabilities and agentic risk

Overview

The skill is transparent about being a trading bot and defaults to paper mode, but live trading needs review because several advertised safety limits are not actually enforced.

Install only if you are comfortable reviewing and operating a live-trading bot. Keep it in paper mode unless you have audited the SDK and fixed or accepted the risk-control gaps; use a narrowly scoped key, keep live credentials separate, and verify final order size, liquidity, resolution timing, and existing open positions before using --live.

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

Error
Location
trader.py:286
Finding

Declared Market Safety Filters Are Not Enforced

Content
View full analysis
None: mode = "LIVE" if live else "PAPER (sim)" safe_print(f"[twitter-bin-decay] mode={mode} max_pos=${MAX_POSITION}") client = get_client(live=live) markets = find_markets(client) safe_print(f"[twitter-bin-decay] {len(markets)} post-count bin markets found") placed = 0 for m in markets: if placed >= MAX_POSITIONS: break side, size, reasoning = compute_signal(m) 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 application loads `MIN_VOLUME` and `MIN_DAYS` as security and risk-management parameters, but neither value is consulted before an order is submitted. Consequently, a ...[truncated 2059 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
trader.py:231
Finding

Minimum Trade Size Can Override the Maximum Position Limit

Content
View full analysis
Remediation
View remediation
MAX_POSITION: raise ValueError( "SIMMER_MIN_TRADE must not exceed SIMMER_MAX_POSITION" ) ``` Apply a final defensive cap to every order: ```python calculated_size = round(conviction * MAX_POSITION, 2) size = min(MAX_POSITION, max(MIN_TRADE, calculated_size)) ``` Additional hardening should include: 1. Modify the configuration schema so invalid minimum/maximum combinations cannot be saved. 2. Centralize sizing in one validated function rather than duplicating the expression across four branches. 3. Confirm the final amount is finite, positive, and no greater than `MAX_POSITION` immediately before `client.trade()`. 4. Fail closed in live mode when any risk parameter is malformed or inconsistent. 5. Add boundary tests for zero conviction, minimum-size orders, equal limits, and `MIN_TRADE > MAX_POSITION`. ]]>

T08 · Insecure Dependencies

Warning
Location
clawhub.json:7
Finding

Trading SDK Dependency Is Not Version or Integrity Pinned

Content
View full analysis
Remediation
View remediation
`. 2. Generate and commit a dependency lock file containing cryptographic hashes for all direct and transitive packages. 3. Install with hash verification enabled, such as pip's `--require-hashes` workflow. 4. Verify that the installed PyPI artifact corresponds to the reviewed upstream source and expected publisher. 5. Review dependency updates before changing the pin; do not automatically consume new releases in live-trading environments. 6. Run the skill in a restricted environment with minimal filesystem and network access. 7. Use a narrowly scoped API key and separate paper-trading credentials from live-trading credentials. 8. Rotate the credential immediately if dependency compromise is suspected. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (3)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill explicitly requires a sensitive environment variable (SIMMER_API_KEY) but does not declare any tool scope or permissions boundary describing that environment access. In an agentic execution environment, undeclared access to credentials reduces reviewability and least-privilege enforcement, and is more concerning here because the key authorizes trading activity, potentially including live financial actions if misconfigured.

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 SIMMER_API_KEY and describes automated trading behavior, but it provides no user-facing disclosure about credential use, outbound network access, or the fact that the skill can place trades on an external platform. In a trading bot context, this omission is security-relevant because users may supply sensitive credentials without understanding the scope of account access and financial actions the skill can perform.

Content

No source excerpt is available for this finding.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · trader.py (reported line 157)May include surrounding context.

python
return 0.5, "no dates, assume neutral"

    now = datetime.now(timezone.utc)
    end = start + __import__('datetime').timedelta(days=period_days)

    if now < start:
        return 0.5, "period not started"