Back to skill

Security audit

Polymarket Supply Chain Trader

Security checks for vulnerabilities and agentic risk

Overview

The skill is a disclosed trading tool, but its live-trading safeguards are materially weaker than the documentation suggests.

Review this carefully before installing for live trading. Paper mode is the default, but do not provide a live-capable SIMMER_API_KEY unless you are comfortable with the actual implemented controls, have scoped spending and trading limits server-side, and have reviewed or pinned the simmer-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 (4)

T08 · Insecure Dependencies

Warning
Location
clawhub.json:3
Finding

Unpinned Privileged Third-Party Trading Dependency

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:232
Finding

Documented Minimum-Volume Safeguard Is Not Enforced

Content
View full analysis
None: mode = "LIVE" if live else "PAPER (sim)" print(f"[polymarket-supply-chain-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-supply-chain-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, ) tag = "(sim)" if r.simulated else "(live)" status ...[truncated 1903 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:27
Finding

Implemented Trading Controls Are Weaker Than the Documented Defaults

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:198
Finding

Minimum-Trade Floor Can Exceed the Configured Maximum Position

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)) edge = p - NO_THRESHOLD return "no", size, f"NO YES={p:.0%} edge={edge:.0%} bias={bias:.2f}x size=${size} — {q[:65]}" ``` The metadata permits contradictory values: ```json { "env": "SIMMER_MAX_POSITION", "default": 25, "range": [ 1, 200 ], "step": 1, "label": "Max position size (USD)", "type": "number" } ``` ```json { "env": "SIMMER_MIN_TRADE", "default": 5, "range": [ 1, 100 ], "step": 1, "label": "Min trade size (USD)", "type": "number" } ``` ### Technical Analysis The sizing algorithm applies `MIN_TRADE` as a floor but does not apply a final `MAX_POSITION` cap. The configuration ranges permit `MAX_POSITION` to be as low as 1 and `MIN_TRADE` to be as high as 100. For example, with `MAX_POSITION=1` and `MIN_TRADE=100`, every qualifying signal produces: ```python size = max(100, conviction * 1) ``` The result is an order of `$100`, despite the configured maximum position being `$1`. This contradicts the code comments and documentation claiming that trade size never exceeds `MAX_POSITION`. ### Attack Path 1. A user or configuration-management interface sets `MIN_TRAD ...[truncated 884 chars]
Remediation
View remediation
MAX_POSITION`. 2. Apply an explicit final cap in both sizing branches. For example: ```python raw_size = max(MIN_TRADE, round(conviction * MAX_POSITION, 2)) size = min(MAX_POSITION, raw_size) ``` 3. Prefer failing closed rather than silently reducing a contradictory configured minimum. 4. Add startup validation for finite, positive numeric values and all relevant cross-field relationships. 5. Restrict the configuration UI so that the minimum-trade upper bound dynamically cannot exceed the selected maximum position. 6. Revalidate the settings after `apply_skill_config()` because it may alter environment variables. 7. Add boundary tests for `MIN_TRADE == MAX_POSITION`, `MIN_TRADE > MAX_POSITION`, zero conviction, and full conviction. 8. Add a final invariant immediately before `client.trade()` that rejects any amount greater than `MAX_POSITION`. ]]>
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
91% confidence
Finding

The skill references environment-based credentials (SIMMER_API_KEY) and describes execution modes that can place live trades, but it does not declare an explicit tool or permission scope. That mismatch weakens least-privilege controls because an agent or platform may expose environment access implicitly without a clear policy boundary, increasing the risk of credential misuse or unintended trading behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest requires a sensitive credential (SIMMER_API_KEY) but provides no user-facing disclosure about why the key is needed, what operations it enables, or how it will be used. In a trading skill, that omission is more dangerous because the credential may permit market access, order placement, or account actions, so users cannot make an informed trust decision before granting it.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.