Back to skill

Security audit

Polymarket Coffee Trader

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed trading skill, but its live-trading safeguards do not reliably enforce the limits users are told they can set.

Review this carefully before installing for live use. Paper mode is disclosed and low risk, but live mode can place real trades with weaker safeguards than advertised; use a tightly limited API key, avoid contradictory tunable settings, and do not rely on the documented volume or portfolio limits until the implementation enforces them.

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:245
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)) ``` ### Technical Analysis The computed order size is protected by a lower bound through `max(MIN_TRADE, ...)`, but it is not subsequently constrained by `MAX_POSITION`. Consequently, the minimum trade setting takes precedence over the maximum position setting whenever `MIN_TRADE` is greater than `MAX_POSITION`. This condition is reachable through the supported configuration. `clawhub.json` permits `SIMMER_MAX_POSITION` to be as low as `1` and `SIMMER_MIN_TRADE` to be as high as `50`. The resulting order can therefore be up to 50 times the configured maximum position. The defect affects both YES and NO orders and applies to live Polymarket execution when the program is launched with `--live`. ### Attack Path 1. Set `SIMMER_MAX_POSITION=1`. 2. Set `SIMMER_MIN_TRADE=50`. 3. Provide a valid `SIMMER_API_KEY`. 4. Run `python trader.py --live`. 5. Allow the market search to find a coffee market whose probability satisfies either trading threshold. 6. `compute_signal()` calculates the size with `max(50, conviction × 1)`. 7. The resulting $50 amount is passed to `client.trade()`, despite the configured $1 maximum. ### Impact Assessment A live order can exceed the user-defined per-trade exposure limit. The immediate scope is the trading authority availabl ...[truncated 319 chars]
Remediation
View remediation
MAX_POSITION: raise ValueError("SIMMER_MIN_TRADE cannot exceed SIMMER_MAX_POSITION") ``` 2. Apply an explicit upper bound to every calculated order: ```python raw_size = round(conviction * MAX_POSITION, 2) size = min(MAX_POSITION, max(MIN_TRADE, raw_size)) ``` 3. Repeat the maximum-amount check immediately before `client.trade()` to provide defense in depth. 4. Add tests covering equal limits, inverted limits, zero or negative values, and the maximum values allowed by `clawhub.json`. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
trader.py:64
Finding

Declared Volume and Concurrent-Position Safeguards Are Not Enforced

Content
View full analysis
= MAX_POSITIONS: break side, size, reasoning = compute_signal(m) if not side: print(f" [skip] {reasoning}") continue ``` `MIN_VOLUME` is loaded but never used to reject a candidate market. In addition, `MAX_POSITIONS` is applied only to the number of successful orders placed during the current process invocation. ### Technical Analysis The project documentation describes `SIMMER_MIN_VOLUME` as a minimum market-volume filter and `SIMMER_MAX_POSITIONS` as the maximum number of concurrent open positions. The implementation does not satisfy either guarantee: - No market-volume check exists in `find_markets()`, `compute_signal()`, or the execution loop. - The local `placed` counter starts at zero on every run and does not include positions already open in the account. - Repeated manual or automated runs can each submit up to `MAX_POSITIONS` additional orders. As a result, users may reasonably believe that configured controls limit liquidity risk and total portfolio exposure when they do not. ### Attack Path #### Low-volume market path 1. Configure a positive `SIMMER_MIN_VOLUME`, such as `5000`. 2. Run the trader with live execution enabled. 3. The keyword search returns a coffee market whose volume is below the configured threshold. 4. Because the code never checks market volume, the market proce ...[truncated 1074 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:226
Finding

Invalid Resolution Timestamps Bypass the Minimum-Days Safety Gate

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
clawhub.json:7
Finding

Trading SDK Dependency Is Not Version-Pinned

Content
View full analysis
Remediation
View remediation
" ] ``` 2. Maintain a lock file containing cryptographic hashes and install with hash verification, such as `pip install --require-hashes`. 3. Review release notes and source changes before updating the pinned version. 4. Use a trusted package index and prevent fallback to untrusted indexes. 5. Run dependency vulnerability and provenance checks in CI. 6. Restrict the API key to the minimum required trading permissions and financial limits so dependency compromise has reduced impact. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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
Findings (2)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill explicitly relies on environment variables such as SIMMER_API_KEY and SIMMER_ENSO_PHASE, but it does not declare any tool scope or permissions boundary for env access. In a trading skill, undeclared credential access weakens least-privilege guarantees and can allow broader-than-expected access to sensitive secrets if the runtime exposes more environment data than intended.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The monitored keyword list includes very broad terms such as 'coffee', 'arabica', 'robusta', and 'coffee market', which can match many unrelated or weakly related markets. In an automated trading context, overbroad discovery criteria can cause the agent to act on irrelevant markets, increasing the chance of unintended trades and financial loss.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.