Back to skill

Security audit

Polymarket Geopolitics Sentiment Reversal Trader

Security checks for vulnerabilities and agentic risk

Overview

This trading skill is transparent about making Polymarket trades, but some promised live-trading safeguards are not actually enforced.

Review this carefully before enabling live mode. Use paper mode first, pin or verify the Simmer SDK version, use a limited and rotatable SIMMER_API_KEY if possible, and do not rely on the advertised minimum-volume or max-open-position controls unless the code is fixed or those limits are enforced elsewhere.

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)

T08 · Insecure Dependencies

Warning
Location
clawhub.json:7
Finding

Unpinned Third-Party Trading SDK Dependency

Content
View full analysis

Vulnerability Details

File Location: clawhub.json:7-9
Vulnerability Type: Supply-chain dependency risk
Risk Level: Medium

Vulnerable Code

json
"pip": [
  "simmer-sdk"
]

Technical Analysis

The project declares simmer-sdk without an exact version or integrity hash. Package installation can therefore resolve to a newer release than the one originally reviewed.

The SDK executes in the same process as the trading skill and receives the high-value SIMMER_API_KEY. It also provides the methods used for market discovery, account context retrieval, configuration loading, and trade submission. A compromised or malicious future release would consequently execute with access to the skill's environment and trading authority.

No evidence indicates that the currently referenced package is malicious. The vulnerability is the absence of controls ensuring that deployments continue using a known, audited package artifact.

Attack Path

  1. An attacker compromises the upstream package publication account, distribution process, or package repository.
  2. The attacker publishes a malicious simmer-sdk release.
  3. A new installation resolves the unpinned dependency to that release.
  4. Python imports the malicious package when trader.py executes.
  5. The package reads SIMMER_API_KEY, manipulates SDK responses, submits unauthorized trades, or transmits account information externally.

Impact Assessment

Exploitation could expose the Simmer API credential and permit actions available to that credential. In live mode, this could include unauthorized Polymarket trades and financial loss. Malicious dependency code would also inherit the filesystem, network, and process privileges granted to the skill runtime.

Remediation
View remediation

Remediation Suggestions

  • Pin simmer-sdk to an exact version that has been reviewed, such as simmer-sdk==X.Y.Z.
  • Use a lock file or hash-verified installation process, such as pip's --require-hashes.
  • Obtain packages only from an approved repository and verify publisher and artifact provenance.
  • Run dependency vulnerability and integrity checks in CI before deployment.
  • Execute the skill with minimal filesystem and network permissions.
  • Scope and rotate SIMMER_API_KEY where supported, particularly after any suspected dependency compromise.

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:51
Finding

Configured Minimum Market Volume Safeguard Is Not Enforced

Content
View full analysis

Vulnerability Details

File Location: trader.py:51-55
Vulnerability Type: Missing financial risk-control enforcement
Risk Level: Medium

Vulnerable Code

python
MAX_POSITION   = float(os.environ.get("SIMMER_MAX_POSITION",  "40"))
MIN_VOLUME     = float(os.environ.get("SIMMER_MIN_VOLUME",    "15000"))
MAX_SPREAD     = float(os.environ.get("SIMMER_MAX_SPREAD",    "0.08"))
MIN_DAYS       = int(os.environ.get(  "SIMMER_MIN_DAYS",      "3"))
MAX_POSITIONS  = int(os.environ.get(  "SIMMER_MAX_POSITIONS", "6"))

MIN_VOLUME is declared and later reloaded from configuration, but no market-volume comparison is performed before client.trade(...) is called.

Technical Analysis

The configuration and documentation present SIMMER_MIN_VOLUME as a minimum market-volume filter. However, compute_signal() validates geopolitical relevance, spread, resolution horizon, and probability thresholds without inspecting market volume.

As a result, modifying SIMMER_MIN_VOLUME has no effect. A market can pass the implemented checks and receive a real order even when its volume is below the operator's configured minimum. Low-volume markets can have weak price discovery, limited executable liquidity, and elevated price-impact risk even when a quoted spread appears acceptable.

This is a fail-open implementation of a documented financial safeguard rather than evidence of intentional malicious behavior.

Attack Path

  1. The operator enables live mode and expects the default $15,000 minimum-volume filter to apply.
  2. Market discovery returns a geopolitical market with probability and spread values that pass the implemented gates.
  3. The market has volume below SIMMER_MIN_VOLUME.
  4. Because the code never evaluates volume, the signal proceeds to client.trade(...).
  5. The live order may execute in an illiquid market and experience poor execution, price impact, or difficulty exiting the position.

Im

...[truncated 316 chars]

Remediation
View remediation

Remediation Suggestions

  • Add an explicit volume check before signal generation or trade submission:

    python
    volume = getattr(market, "volume", None)
    if volume is None:
        return None, 0, "Market volume unavailable"
    if volume < MIN_VOLUME:
        return None, 0, f"Volume ${volume:,.2f} below minimum ${MIN_VOLUME:,.2f}"
    
  • Confirm the SDK's authoritative volume field and units rather than assuming an attribute name.

  • Fail closed when volume is unavailable or malformed, especially in live mode.

  • Add automated tests proving that markets below, equal to, and above the configured threshold are handled correctly.

  • Log the evaluated market volume and threshold for auditability.

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:263
Finding

Maximum Position Limit Counts Only Orders Placed During the Current Run

Content
View full analysis

Vulnerability Details

File Location: trader.py:263-266
Vulnerability Type: Incomplete exposure-limit enforcement
Risk Level: Medium

Vulnerable Code

python
placed = 0
for m in markets:
    if placed >= MAX_POSITIONS:
        break

The counter is incremented only after a successful trade in the current invocation:

python
if r.success:
    placed += 1

Technical Analysis

MAX_POSITIONS is documented as the maximum number of concurrent open positions, but the implementation only limits successful orders placed by one execution of run().

The code does not query the account's existing open positions before placing new orders. Consequently, pre-existing positions and orders from earlier executions are excluded from the limit. Repeated manual, cron, or managed-automation invocations can each place up to MAX_POSITIONS additional orders.

The implementation also counts successful order submissions rather than confirming the resulting number of distinct concurrent positions. This makes the configured control a per-run order cap rather than the advertised account exposure cap.

Attack Path

  1. The live account already contains open positions, or the skill completes an earlier run that creates positions.
  2. The skill is invoked again while those positions remain open.
  3. placed is initialized to zero without querying account state.
  4. The new invocation submits up to MAX_POSITIONS additional successful orders.
  5. Repeated invocations continue increasing aggregate exposure beyond the configured maximum.

This path can occur through normal repeated operation; no external attacker is required. An actor capable of repeatedly triggering the managed skill could amplify the exposure.

Impact Assessment

The issue does not provide operating-system privilege escalation. It affects the trading authority associated with SIMMER_API_KEY and can cause cumulative live exp ...[truncated 229 chars]

Remediation
View remediation

Remediation Suggestions

  • Query authoritative account state before submitting any order.
  • Count existing open positions and relevant pending orders.
  • Calculate available capacity as MAX_POSITIONS - existing_positions.
  • Stop trading when the available capacity is zero or negative.
  • Deduplicate by market where multiple orders in the same market represent one position.
  • Recheck exposure immediately before each live trade to reduce race conditions.
  • Where concurrent executions are possible, enforce the limit server-side or use transactional locking rather than relying only on an in-process counter.
  • Rename the setting to MAX_ORDERS_PER_RUN if per-run behavior is intended, and introduce a separate account-wide concurrent-position limit.
  • Add tests covering existing positions, pending orders, repeated runs, and concurrent invocations.
Vulnerability Patterns
  • 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
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (1)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill explicitly requires a high-value environment credential (SIMMER_API_KEY) but does not declare any tool scope, permissions, or allowed-tools boundary. That mismatch weakens least-privilege controls and can let an agent load or expose credentials more broadly than intended, which is especially sensitive in a trading skill where the key authorizes real-money actions when live mode is enabled.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.