Back to skill

Security audit

Simmer Momentum Trader

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed trading skill, but its automated financial behavior has safety and accuracy gaps users should review before installing.

Review this before installing, especially if enabling --live or running it on a schedule. Use a narrowly scoped Simmer API key, set conservative server-side account limits, verify the actual strategy matches your expectations, and consider fixing fail-closed safeguards, dependency pinning, and numeric validation before allowing real orders.

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
simmer_momentum_trader.py:111
Finding
Market safeguards fail open when context retrieval fails## Vulnerability Details **File Location**: `simmer_momentum_trader.py`, lines 111-119 **Vulnerability Type**: Fail-open financial safety control **Risk Level**: High ### Vulnerable Code ```python client = get_client() try: params = {} if my_probability is not None: params["my_probability"] = my_probability context = client.get_market_context(market_id, **params) except Exception: return None # Can't check context, proceed with caution ``` The caller interprets `None` as approval to continue: ```python skip_reason = should_skip_market(market_id) if skip_reason: print(f" SKIPPED: {skip_reason}") print() continue ``` ### Technical Analysis `should_skip_market()` is intended to prevent trades when severe flip-flop warnings, excessive slippage, or an unfavorable edge recommendation are present. However, every exception raised while retrieving market context is converted into `None`. The function also uses `None` to mean that no reason exists to skip the market. Consequently, authentication errors, network timeouts, rate limiting, malformed responses, SDK failures, and service outages all bypass the advertised safety checks. This is a fail-open design. It also contradicts the documented hard rule in `SKILL.md` that market context is always checked before trading. Although `calculate_signal()` performs another context request, the two requests are independent: the safety request can fail while the later signal request succeeds. ### Attack Path 1. The trader is invoked with `--live`, enabling real orders. 2. An attacker or infrastructure failure disrupts the context request made by `should_skip_market()`. 3. `get_market_context()` raises an exception. 4. The broad exception handler returns `None`. 5. The caller treats this value as approval to proceed. 6. A subsequent context request in `calculate_signal()` succeeds and generates a signal. 7. `execute_tra ...[truncated 561 chars]
Remediation
## Remediation Suggestions Fail closed whenever safety context cannot be obtained: ```python except Exception as exc: return f"Unable to verify market safeguards: {exc}" ``` Additional hardening should include: 1. Catch only expected SDK or network exceptions rather than all `Exception` subclasses. 2. Log the failure type without exposing credentials or sensitive response data. 3. Add bounded retries with exponential backoff for transient failures. 4. Require successful validation of flip-flop status, slippage, and edge analysis before every live order. 5. Use a structured result that distinguishes `SAFE`, `UNSAFE`, and `CHECK_FAILED`, rather than overloading `None`. 6. If fail-open behavior is operationally necessary, place it behind an explicit unsafe command-line option that is disabled by default and emits a prominent warning. 7. Add automated tests proving that context exceptions prevent `client.trade()` from being called.

T08 · Insecure Dependencies

Warning
Location
clawhub.json:3
Finding
Privileged trading dependency is installed without version or integrity constraints## Vulnerability Details **File Location**: `clawhub.json`, lines 3-5 **Vulnerability Type**: Unpinned third-party dependency **Risk Level**: Medium ### Vulnerable Code ```json "requires": { "pip": ["simmer-sdk"], "env": ["SIMMER_API_KEY"] }, ``` The script imports the unconstrained package and provides it with the trading credential: ```python from simmer_sdk import SimmerClient ``` ```python _client = SimmerClient( api_key=os.environ["SIMMER_API_KEY"], venue="polymarket", ) ``` ### Technical Analysis The project declares `simmer-sdk` without an exact version, lock file, or artifact hash. Installation can therefore select a package release that was not reviewed with this skill. This dependency executes as imported Python code and receives the `SIMMER_API_KEY`. It also implements market-context retrieval and live order submission. A compromised upstream release, compromised package repository, or unexpectedly incompatible future release would consequently execute with the same process access as the trader. No evidence shows that the current package is malicious. The vulnerability is the absence of supply-chain controls around a dependency with direct access to credentials and financial operations. ### Attack Path 1. An attacker compromises the upstream package, its publisher account, or its distribution channel. 2. A malicious or altered `simmer-sdk` release is published. 3. The skill environment installs the unconstrained package name and selects that release. 4. Python executes attacker-controlled initialization code when `simmer_sdk` is imported. 5. The altered dependency can read the process environment, receive the API key, manipulate market data, or alter calls intended to submit trades. ### Impact Assessment Successful exploitation would provide code execution with the privileges of the skill process. The compromised dependency could access environment variables avail ...[truncated 303 chars]
Remediation
## Remediation Suggestions 1. Pin `simmer-sdk` to an exact, reviewed version rather than accepting any available release. 2. Record cryptographic hashes in a requirements or lock file and require hash verification during installation. 3. Install packages only from a trusted, explicitly configured package index. 4. Review release provenance, publisher identity, source repository, and package signatures where available. 5. Run dependency vulnerability and integrity scanning in CI before deployment. 6. Use a narrowly scoped trading credential with server-side market, amount, and withdrawal restrictions. 7. Perform upgrades through a controlled review process instead of automatically accepting new releases.

T09 · Insecure Skill Coding Practices

Warning
Location
simmer_momentum_trader.py:24
Finding
Trade amount and divergence threshold lack numeric safety validation## Vulnerability Details **File Location**: `simmer_momentum_trader.py`, lines 24-25 **Vulnerability Type**: Improper validation of financial configuration **Risk Level**: Medium ### Vulnerable Code ```python DIVERGENCE_THRESHOLD = float(os.environ.get("DIVERGENCE_THRESHOLD", "0.08")) TRADE_AMOUNT = float(os.environ.get("TRADE_AMOUNT", "5.0")) ``` The threshold can also be replaced through the command line without range validation: ```python parser.add_argument("--threshold", type=float, default=DIVERGENCE_THRESHOLD, help=f"Divergence threshold (default: {DIVERGENCE_THRESHOLD})") ``` The unvalidated amount is then passed to the trading SDK: ```python result = client.trade( market_id=market_id, side=signal["side"], amount=TRADE_AMOUNT, source=TRADE_SOURCE, skill_slug=SKILL_SLUG, reasoning=signal["reasoning"], ) ``` ### Technical Analysis Converting a value with `float()` verifies only that Python can parse it. It does not establish that the result is finite, positive, or within an acceptable financial range. Values such as negative numbers, zero, `nan`, `inf`, or an unexpectedly large amount are accepted locally. A negative threshold may cause nearly every market divergence to pass the signal filter. A non-finite threshold can produce unexpected comparison behavior. An excessive or non-finite trade amount can reach `client.trade()` during live execution. The upstream SDK or API may reject some malformed values, but the project does not enforce that assumption. Financial safety constraints should be validated before an order reaches a third-party boundary. ### Attack Path 1. An attacker with influence over the runtime environment, deployment configuration, or command arguments supplies an unsafe `TRADE_AMOUNT` or divergence threshold. 2. Python parses the input as a floating-point value without checking its range or finiteness. 3. The unsafe thre ...[truncated 750 chars]
Remediation
## Remediation Suggestions Validate all financial and probability configuration immediately after parsing: ```python import math if not math.isfinite(DIVERGENCE_THRESHOLD) or not 0 < DIVERGENCE_THRESHOLD <= 1: raise ValueError("DIVERGENCE_THRESHOLD must be finite and in the range (0, 1]") if not math.isfinite(TRADE_AMOUNT) or not 0 < TRADE_AMOUNT <= MAX_TRADE_AMOUNT: raise ValueError("TRADE_AMOUNT must be finite, positive, and within the configured limit") ``` Additional controls should include: 1. Define a conservative, explicit maximum trade amount. 2. Add per-market, per-run, and daily aggregate spending limits. 3. Apply the same validation to environment values and command-line overrides. 4. Abort before creating the API client if configuration is invalid. 5. Retain server-side limits even after local validation to provide defense in depth. 6. Add tests for zero, negative, `nan`, positive and negative infinity, boundary values, and excessively large values.
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • 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 (3)

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill references environment-based secrets and configuration such as `SIMMER_API_KEY` but does not declare an explicit tool scope or permissions model in the manifest. That creates an authorization ambiguity where an agent runtime may expose broader environment access than reviewers or users expect, increasing the risk of secret access or misuse if the skill is remixed or extended.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The function and module documentation claim a momentum signal based on divergence from a recent average, but the implementation instead compares current probability to edge_analysis.estimated_probability or a fixed 0.5 baseline. In an automated trading skill, this mismatch is dangerous because operators may believe they are deploying a history-based momentum strategy when they are actually placing live or dry-run trades using a materially different signal, leading to unintended financial risk and invalid risk assumptions.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The advertised behavior says the skill detects momentum and divergence from recent market behavior, but the actual logic never uses recent price history. In the context of a trading bot that can execute live trades with --live, this is a real security/integrity issue because users may rely on false strategy claims, causing unreviewed automated orders under incorrect assumptions about how signals are generated.

Static analysis

No suspicious patterns detected.