Back to skill

Security audit

Trading

Security checks for vulnerabilities and agentic risk

Overview

This trading skill is mostly coherent, but its advertised dry run can still make an authenticated remote Simmer market-import/share request before stopping short of a trade.

Review this carefully before installing. Only use it with a Simmer API key you are willing to grant trading-related account access to, do not assume dry-run is side-effect free, and run it in a controlled Python environment without untrusted tradejournal modules on the import path. Treat any cron or heartbeat setup as live automated trading and set strict position limits.

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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
fastloop_trader.py:632
Finding

Dry-run mode performs an authenticated remote market import

Content
View full analysis

Vulnerability Details

File Location: fastloop_trader.py:364-370 and fastloop_trader.py:632-641
Vulnerability Type: Dry-run side effect and unnecessary credential use
Risk Level: Medium

Vulnerable Code

python
def import_fast_market_market(api_key, slug):
    """Import a fast market to Simmer. Returns market_id or None."""
    url = f"https://polymarket.com/event/{slug}"
    result = simmer_request("/api/sdk/markets/import", method="POST", data={
        "polymarket_url": url,
        "shared": True,
    }, api_key=api_key)
python
# Step 5: Import & Trade
log(f"\n🔗 Importing to Simmer...", force=True)
market_id, import_error = import_fast_market_market(api_key, best["slug"])

if not market_id:
    log(f"  ❌ Import failed: {import_error}", force=True)
    return

log(f"  ✅ Market ID: {market_id[:16]}...", force=True)

if dry_run:
    est_shares = position_size / price if price > 0 else 0
    log(f"  [DRY RUN] Would buy {side.upper()} ${position_size:.2f} (~{est_shares:.1f} shares)", force=True)

Technical Analysis

The market-import operation is executed before the dry_run condition is evaluated. The import is an authenticated HTTP POST to the Simmer API and explicitly includes "shared": True.

Consequently, default dry-run execution is not side-effect free. When the strategy identifies a qualifying signal, it can create or share remote market state and consume account import quota even though no trade is submitted. This conflicts with the documented expectation that dry-run mode only reports what would happen.

The behavior also exceeds minimum privilege for simulation: local market analysis and trade estimation do not require an authenticated import or the use of SIMMER_API_KEY.

Attack Path

  1. A user follows the documented default invocation and runs the script without --live.
  2. The script loads SIMMER_API_KEY and discovers a qual ...[truncated 1022 chars]
Remediation
View remediation

Remediation Suggestions

  • Move the dry-run branch before import_fast_market_market() so simulation performs no authenticated mutation.
  • Calculate estimated position size and shares using discovered public market data, then return before any import or trade request.
  • Delay get_api_key() until an operation genuinely requires authentication. Public-data dry runs should work without SIMMER_API_KEY.
  • If dry-run import testing is necessary, add a separate explicit option such as --test-import, clearly document its remote effects, and default "shared" to False.
  • Add automated tests that assert dry-run mode never invokes authenticated POST, PUT, PATCH, or DELETE requests.
  • Document exactly which commands can mutate remote account state.

T08 · Insecure Dependencies

Warning
Location
fastloop_trader.py:27
Finding

Automatic import of an undeclared ambient trade-journal module enables dependency shadowing

Content
View full analysis

Vulnerability Details

File Location: fastloop_trader.py:27-39
Vulnerability Type: Unpinned optional dependency loaded from the ambient Python import path
Risk Level: Medium

Vulnerable Code

python
# Optional: Trade Journal integration
try:
    from tradejournal import log_trade
    JOURNAL_AVAILABLE = True
except ImportError:
    try:
        from skills.tradejournal import log_trade
        JOURNAL_AVAILABLE = True
    except ImportError:
        JOURNAL_AVAILABLE = False
        def log_trade(*args, **kwargs):
            pass

Technical Analysis

The script automatically imports tradejournal or skills.tradejournal without declaring, pinning, or validating the dependency. Python resolves these names through sys.path, which commonly includes the script directory, current environment, installed packages, and paths supplied through PYTHONPATH.

Importing a Python module executes its top-level code immediately. Therefore, a malicious file or package that shadows either expected module name can run arbitrary code as soon as the trader starts. This can occur even in dry-run mode because the import takes place before command-line processing and strategy execution.

The integration is optional but automatically enabled whenever a matching module can be resolved. This violates least-surprise and supply-chain hardening principles because the script neither requires explicit operator consent nor verifies that the imported module is the intended implementation.

Attack Path

  1. An attacker gains the ability to place a file named tradejournal.py, create a skills/tradejournal.py package path, modify PYTHONPATH, or install a malicious package under one of those names.
  2. The operator launches fastloop_trader.py.
  3. Python resolves the attacker-controlled module before the intended implementation.
  4. The module's top-level code executes with the same operating-system per ...[truncated 1295 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove the implicit ambient import if trade-journal integration is not essential to the declared trading functionality.
  • Require an explicit command-line or configuration opt-in before loading the integration.
  • Declare the dependency in a locked dependency manifest with an exact version and verified hashes.
  • Import only from a project-controlled, fully qualified package namespace rather than trying generic top-level names.
  • Package the trusted journal adapter with the Skill if its source can be reviewed and maintained securely.
  • Validate the resolved module origin using importlib.util.find_spec() and reject modules outside an approved installation directory.
  • Run the trader in an isolated virtual environment with a controlled sys.path; do not include attacker-writable directories or untrusted PYTHONPATH entries.
  • Avoid passing sensitive trade metadata to optional extensions unless the operator explicitly authorizes it.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (8)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill advertises executable behavior that uses environment secrets, file/config writes, and network access, but it does not declare an explicit tool scope such as permissions or allowed-tools. That creates a least-privilege gap: an agent may invoke the skill with broader capabilities than intended, increasing the chance of unintended secret exposure, unauthorized external requests, or persistent config changes.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The description says to use the skill whenever a user wants to automate short-term crypto trading or use CEX momentum as a signal, which is broad enough to encourage opportunistic invocation without strong user confirmation or suitability checks. In a live-trading skill that can place real-money trades, ambiguous activation criteria materially increase the risk of accidental or overly eager execution.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The 'When to Use This Skill' section lists broad situations like automating short-term crypto prediction trading and monitoring sprint positions, but it does not define exclusions or safeguards. Given the skill's context—real USDC trading on Polymarket and support for looping/cron execution—this ambiguity makes unintended activation more dangerous than in a read-only or educational skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The _update_config function writes directly to config.json, modifying local files, but the function itself has no inline warning, confirmation, or explanatory comment about persisting changes. Although the CLI exposes --set, the actual file-write path is a safety-relevant operation that lacks explicit user disclosure in the code at the write site.

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
83% confidence
Finding

The manifest frames the skill as a fast-market trading agent using Simmer API and CEX momentum signals. The code additionally imports and uses a tradejournal integration to record executed trades, which is a separate persistence/integration behavior not disclosed in the stated description.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The manifest describes a trading skill driven by CEX momentum signals, but does not mention local state/config file modification. While configuration support is useful operationally, writing config.json is a behavior beyond the narrowly described trade-execution role.

Content

No source excerpt is available for this finding.