Back to skill

Security audit

Polymarket Food Agriculture Trader

Security checks for vulnerabilities and agentic risk

Overview

This automated trading skill is transparent about real-money use, but its risk controls do not fully match what it promises.

Review this carefully before installing. It defaults to paper trading and requires --live for real Polymarket orders, but do not rely on the documented minimum-volume or maximum-position safeguards until they are fixed and tested. Use a tightly scoped API key, keep live limits low, and pin/review the trading SDK dependency.

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:303
Finding

Minimum Market Volume Safeguard Is Not Enforced

Content
View full analysis
None: mode = "LIVE" if live else "PAPER (sim)" print(f"[polymarket-food-agriculture-trader] mode={mode} max_pos=${MAX_POSITION} min_vol=${MIN_VOLUME} max_spread={MAX_SPREAD:.0%} min_days={MIN_DAYS}") client = get_client(live=live) markets = find_markets(client) print(f"[polymarket-food-agriculture-trader] {len(markets)} candidate markets") placed = 0 for m in markets: if placed >= MAX_POSITIONS: break side, size, reasoning = compute_signal(m) if not side: print(f" [skip] {reasoning}") continue ok, why = context_ok(client, m.id) if not ok: 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, ) ``` ### Technical Analysis The application reads `SIMMER_MIN_VOLUME` and displays its value, but it never compares this threshold against a market's trading volume. Markets returned by `find_markets()` proceed directly through signal, context, and order-submission logic. This contradicts the documented purpose of `SIMMER_MIN_VOLUME` as a minimum-volume market filter. A configured safeguard that is not enforced creates a false sense of protection, particularly in live mode. Low-volume prediction markets are more susceptible to: - High price impact and poor execution. - Market-price manipulation. - Unreliable probability signals. - Difficulty exiting a position. - Slippage no ...[truncated 1105 chars]
Remediation
View remediation
bool: try: volume = float(market.volume) except (AttributeError, TypeError, ValueError): return False return volume >= MIN_VOLUME ``` Use the check in the trading loop: ```python for m in markets: if not market_has_sufficient_volume(m): print(f" [skip] Insufficient or unavailable market volume") continue ``` Additional hardening should include: 1. Treat missing, malformed, stale, or negative volume as a failure rather than allowing the trade. 2. Confirm which SDK field represents the relevant volume and whether it is expressed in USD, USDC, cents, or another unit. 3. Consider requiring both minimum total volume and minimum order-book depth. 4. Revalidate liquidity immediately before live order submission. 5. Add tests proving that markets below the threshold, with missing volume, and with malformed volume never reach `client.trade()`. 6. Reconcile the documented default in `SKILL.md` with the effective default in `clawhub.json` and `trader.py`. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:269
Finding

Minimum Trade Floor Can Bypass the Maximum Position Limit

Content
View full analysis
= NO_THRESHOLD: conviction = min(1.0, (p - NO_THRESHOLD) / (1 - NO_THRESHOLD) * bias) size = max(MIN_TRADE, round(conviction * MAX_POSITION, 2)) ``` The allowed configuration ranges are: ```json { "env": "SIMMER_MAX_POSITION", "default": 20, "range": [ 1, 200 ], "step": 1, "label": "Max position size (USD)" } ``` ```json { "env": "SIMMER_MIN_TRADE", "type": "number", "default": 5, "range": [ 1, 100 ], "step": 1, "label": "Min trade size (USD)" } ``` ### Technical Analysis The order size is calculated with: ```python max(MIN_TRADE, conviction * MAX_POSITION) ``` This applies a lower bound but does not subsequently apply a hard upper bound. If `MIN_TRADE` is greater than `MAX_POSITION`, the selected size is `MIN_TRADE`, directly violating the maximum-position limit. The configuration schema independently permits `MAX_POSITION` as low as `1` and `MIN_TRADE` as high as `100`. No validation ensures that: ```text MIN_TRADE <= MAX_POSITION ``` Environment variables can also supply values without range or relationship validation. For example: ```text SIMMER_MAX_POSITION=1 SIMMER_MIN_TRADE=100 ``` Any qualifying signal produces an order of at least $100, despite the stated $1 maximum. This contradicts the documentation's claim that sizing i ...[truncated 1214 chars]
Remediation
View remediation
None: if MAX_POSITION <= 0: raise ValueError("MAX_POSITION must be positive") if MIN_TRADE <= 0: raise ValueError("MIN_TRADE must be positive") if MIN_TRADE > MAX_POSITION: raise ValueError("MIN_TRADE must not exceed MAX_POSITION") ``` Apply an explicit hard cap when calculating the amount: ```python calculated = round(conviction * MAX_POSITION, 2) size = min(MAX_POSITION, max(MIN_TRADE, calculated)) ``` Further hardening should include: 1. Add schema-level cross-field validation where the configuration platform supports it. 2. Adjust individual ranges so obviously incompatible combinations cannot be selected. 3. Validate environment-derived values for finiteness, sign, range, and relationships. 4. Fail closed before client creation or market discovery if risk parameters are invalid. 5. Revalidate the final amount immediately before `client.trade()`. 6. Add unit tests for `MIN_TRADE < MAX_POSITION`, equality, `MIN_TRADE > MAX_POSITION`, zero, negative, NaN, infinity, and out-of-range inputs. 7. Ensure cumulative exposure is also constrained separately from the per-order maximum. ]]>

T08 · Insecure Dependencies

Note
Location
clawhub.json:5
Finding

Security-Critical Trading SDK Dependency Is Unpinned

Content
View full analysis
Remediation
View remediation
" ] ``` Where supported, also: 1. Generate and enforce a lockfile containing transitive dependency versions. 2. Require package hashes so installation verifies artifact integrity. 3. Install only from an explicitly trusted package index. 4. Review package ownership, release history, source repository, and published artifacts. 5. Run dependency vulnerability and provenance scanning in CI. 6. Test upgrades in an isolated environment before changing the pinned version. 7. Restrict the skill process using least-privilege filesystem access and outbound-network allowlists. 8. Scope and rotate `SIMMER_API_KEY`, and use separate credentials for simulated and live trading if supported. 9. Alert on dependency changes and require manual approval for updates to the trading SDK. ]]>
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
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

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 an API credential and points to an automated trading entrypoint, but it does not surface any user-facing disclosure that the skill will place networked trades using provided credentials. In a trading context, this omission is dangerous because users may enable the skill without understanding that it can autonomously access an external service and execute financially meaningful actions.

Content

No source excerpt is available for this finding.