Back to skill

Security audit

Polymarket Fast Loop

Security checks for vulnerabilities and agentic risk

Overview

This skill is mostly coherent as a real-money Polymarket trading bot, but it has an undocumented endpoint override that can send the Simmer API key to an untrusted server.

Review before installing. Use a scoped, revocable Simmer API key, keep SIMMER_API_BASE unset unless you fully trust and control the destination, start in dry-run mode, and do not place --live in cron or heartbeat automation until you are comfortable with the trading logic, position size, and loss risk.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
fastloop_trader.py:153
Finding

Unrestricted API Base Override Can Exfiltrate the Simmer API Key

Content
View full analysis

Vulnerability Details

File Location: fastloop_trader.py, lines 153 and 190–194
Vulnerability Type: Unvalidated authenticated API endpoint override
Risk Level: High

Vulnerable Code

python
SIMMER_BASE = os.environ.get("SIMMER_API_BASE", "https://api.simmer.markets")
python
def simmer_request(path, method="GET", data=None, api_key=None):
    """Make a Simmer API request."""
    headers = {}
    if api_key:
        headers["Authorization"] = f"Bearer {api_key}"
    return _api_request(f"{SIMMER_BASE}{path}", method=method, data=data, headers=headers)

Authenticated requests may include sensitive account and transaction operations:

python
def execute_trade(api_key, market_id, side, amount):
    """Execute a trade on Simmer."""
    return simmer_request("/api/sdk/trade", method="POST", data={
        "market_id": market_id,
        "side": side,
        "amount": amount,
        "venue": "polymarket",
        "source": TRADE_SOURCE,
    }, api_key=api_key)

Technical Analysis

The SIMMER_API_BASE environment variable controls the destination of every Simmer API request. The value is accepted without validating its scheme, hostname, port, or TLS requirements. At the same time, simmer_request() attaches the secret SIMMER_API_KEY as a bearer token to requests sent to that destination.

The declared functionality only requires authenticated communication with https://api.simmer.markets. Allowing an undocumented, unrestricted endpoint override exceeds that minimum requirement and creates a credential-exfiltration channel.

The affected calls include portfolio retrieval, position retrieval, market import, and real trade execution. Consequently, an attacker-controlled endpoint can receive the bearer credential as well as market identifiers, order direction, order amount, venue, and strategy source metadata. It can also return crafted JSON responses that the ...[truncated 1779 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the production runtime override and use a fixed trusted endpoint:

    python
    SIMMER_BASE = "https://api.simmer.markets"
    
  2. If endpoint overrides are necessary for development or testing, require an explicit development-mode flag and enforce a strict allowlist:

    python
    from urllib.parse import urlparse
    
    ALLOWED_SIMMER_HOSTS = {"api.simmer.markets"}
    
    def validate_simmer_base(value):
        parsed = urlparse(value)
        if parsed.scheme != "https":
            raise ValueError("SIMMER API endpoint must use HTTPS")
        if parsed.hostname not in ALLOWED_SIMMER_HOSTS:
            raise ValueError("Untrusted SIMMER API hostname")
        if parsed.username or parsed.password:
            raise ValueError("User information is not permitted in the endpoint")
        if parsed.port not in (None, 443):
            raise ValueError("Unexpected SIMMER API port")
        if parsed.query or parsed.fragment:
            raise ValueError("Query strings and fragments are not permitted")
        return value.rstrip("/")
    
  3. Do not attach authorization headers until the final request URL has been verified as HTTPS and matched against the exact trusted hostname.

  4. Disable or strictly validate cross-origin redirects for authenticated requests so credentials cannot be forwarded to another host.

  5. Use narrowly scoped, revocable API tokens. Separate read-only credentials from credentials capable of executing trades where supported.

  6. Document every supported endpoint override and ensure production cron jobs, containers, and launch wrappers define environments from trusted, access-controlled configuration.

  7. Rotate the API key if the script has previously run with an untrusted or unknown SIMMER_API_BASE value.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (9)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill requests or implies access to environment secrets, file writes, and network activity, but does not declare any explicit tool scope or permissions boundary. In a live-trading skill that can place real-money orders and uses an API key, this increases the chance of over-privileged execution, unintended data exposure, or unauthorized external actions if the skill is invoked in a broader agent context.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The description and usage guidance are broad enough that an orchestrator could invoke this skill for generic short-term trading requests, even when the user did not specifically intend Polymarket fast-market execution. Because the skill can lead to live financial trades with real USDC, overbroad triggering raises the risk of unintended or mismatched automation in a high-consequence context.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill's stated purpose is to trade fast Polymarket markets based on CEX momentum signals, but the code also writes arbitrary strategy settings to a local config.json file via _update_config and exposes this through the --set CLI path. Persistently modifying local files is not an obvious requirement of executing the trading strategy itself.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · fastloop_trader.py (reported line 292)May include surrounding context.

python
Returns: {momentum_pct, direction, price_now, price_then, avg_volume, candles}
    """
    url = (
        f"https://api.binance.com/api/v3/klines"
        f"?symbol={symbol}&interval=1m&limit={lookback_minutes}"
    )
    result = _api_request(url)

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · fastloop_trader.py (reported line 333)May include surrounding context.

python
def get_coingecko_momentum(asset="bitcoin", lookback_minutes=5):
    """Fallback: get price from CoinGecko (less accurate, ~1-2 min lag)."""
    url = f"https://api.coingecko.com/api/v3/simple/price?ids={asset}&vs_currencies=usd"
    result = _api_request(url)
    if not result or isinstance(result, dict) and result.get("error"):
        return None

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The manifest says the skill trades Polymarket BTC 5-minute and 15-minute fast markets, but the file-level docstring states only '5-minute fast markets' and the implementation defaults to WINDOW='5m'. Although 15m is configurable in code, the primary documented behavior in this file is narrower than the manifest claim, creating a mild description/behavior inconsistency.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The top-level docstring frames the skill as trading Polymarket BTC markets with Binance BTCUSDT candles as the signal, but the actual implementation supports multiple assets and multiple signal sources via configuration. This is an active documentation mismatch about what the code is designed to do, not merely an omitted implementation detail.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The manifest describes a trading skill using Simmer API and CEX momentum signals, but the code optionally imports an external tradejournal module and logs executed trade metadata to it. This auxiliary integration is not mentioned in the stated purpose and is not necessary to place or evaluate trades.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code performs a file write to config.json, replacing persisted configuration values, but the write path itself has no inline warning comment or disclosure about modifying local files. Although the CLI help mentions 'Update config' and 'Or edit config.json directly,' the file-writing operation lacks a clearer user warning at the point of action about overwriting on-disk configuration.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.