Back to skill

Security audit

Kalshi F1 Race Momentum Trader

Security checks for vulnerabilities and agentic risk

Overview

This is a real-money trading skill with a disclosed dry-run default, but its credential scope and live-trading safety controls are too broad for automatic approval.

Review before installing. Use only dedicated, low-balance trading credentials, avoid providing a broad wallet private key unless you understand why live DFlow/Solana execution needs it, keep the skill in dry-run until you have validated the static model inputs, and prefer a pinned simmer-sdk version plus stronger live-trade confirmation and fail-closed safeguards.

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

Error
Location
trader.py:345
Finding

Market-context failures bypass live-trading safeguards

Content
View full analysis

Vulnerability Details

File Location: trader.py, lines 345–361
Vulnerability Type: Fail-open safety validation
Risk Level: High

python
def get_market_context(market_id: str, my_probability: float = None) -> dict:
    """Get market context with safeguards and edge analysis."""
    try:
        if my_probability is not None:
            return get_client()._request(
                "GET", f"/api/sdk/context/{market_id}",
                params={"my_probability": my_probability}
            )
        return get_client().get_market_context(market_id)
    except Exception:
        return None


def check_safeguards(context: dict) -> tuple[bool, list[str]]:
    """Check context for safeguards. Returns (should_trade, reasons)."""
    if not context:
        return True, []

Technical Analysis

get_market_context() catches every exception and converts the failure into a None result without recording the underlying cause. check_safeguards() then treats missing context as approval by returning (True, []).

Consequently, failure to retrieve or parse market context bypasses all subsequent safeguards, including:

  • Resolved-market detection
  • Severe flip-flop detection
  • Minimum time-to-resolution enforcement
  • Minimum-liquidity enforcement
  • Maximum-slippage enforcement

This is a fail-open design in a financially privileged execution path. The affected check is used before entry orders and exit orders. In live mode, an approved result allows execute_trade() to submit an actual order through the Simmer SDK.

Attack Path

  1. The Skill is started with python trader.py --live.
  2. A trading signal or exit condition is identified.
  3. Retrieval of /api/sdk/context/{market_id} fails because of a network interruption, rate limit, malformed response, SDK error, service outage, or deliberate interference with connectivity.
  4. get_market_context() suppresses the exceptio ...[truncated 781 chars]
Remediation
View remediation

Remediation Suggestions

  1. Fail closed whenever market context cannot be obtained:

    python
    def check_safeguards(context: dict) -> tuple[bool, list[str]]:
        if not context:
            return False, ["Unable to retrieve market context"]
    
  2. Preserve a sanitized error reason rather than silently discarding every exception. Do not include API keys, authorization headers, or full sensitive response bodies in logs.

  3. Add bounded retries with exponential backoff for transient failures. If all retries fail, skip the order.

  4. Validate the response schema before approving a trade. Missing market, warnings, discipline, or slippage data should result in rejection where the corresponding control cannot be evaluated.

  5. Distinguish explicitly between “safeguard passed” and “safeguard unavailable.” Only the former should authorize live execution.

  6. Add automated tests covering network exceptions, empty dictionaries, malformed context objects, rate limits, and SDK errors. Each case should verify that no live trade is attempted.

T08 · Insecure Dependencies

Warning
Location
clawhub.json:3
Finding

Privileged third-party trading dependency is not version-pinned

Content
View full analysis

Vulnerability Details

File Location: clawhub.json, lines 3–10
Vulnerability Type: Unpinned privileged dependency
Risk Level: Medium

json
"requires": {
  "env": [
    "SIMMER_API_KEY",
    "SOLANA_PRIVATE_KEY"
  ],
  "pip": [
    "simmer-sdk"
  ]
},

The same unpinned requirement is documented in SKILL.md:

yaml
requires_pip: "simmer-sdk"

Technical Analysis

The package requests simmer-sdk without an exact version, lockfile, or integrity hash. Installation can therefore resolve to a different package release over time.

This dependency operates in a highly privileged position. Project code imports configuration and client functionality from it, initializes SimmerClient with SIMMER_API_KEY, makes authenticated network requests, and invokes its trading method. As Python code executing in the same process, the dependency can also access the process environment, including any injected SOLANA_PRIVATE_KEY.

The reviewed project does not demonstrate that the dependency is malicious. The vulnerability is the absence of reproducible dependency controls around a component entrusted with valuable credentials and live-trading authority.

Attack Path

  1. An attacker compromises the package publisher account or distribution pipeline, or an unsafe future release is published under the expected package name.
  2. A new Skill installation resolves the unpinned simmer-sdk requirement to that release.
  3. Python imports the dependency during startup and executes its module-level code in the Skill process.
  4. The compromised dependency reads environment credentials, changes network destinations, alters market data, or modifies trade requests.
  5. It can exfiltrate credentials or submit unauthorized transactions using the authority available to the process.

This path is conditional on compromise or unsafe modification of the upstream dependency; no such compromise was establish ...[truncated 653 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin simmer-sdk to a reviewed exact version in both clawhub.json and SKILL.md, for example simmer-sdk==X.Y.Z.

  2. Use a lockfile or hash-verified installation, such as pip requirements with --require-hashes, to ensure reproducible package contents.

  3. Verify package provenance and maintain an explicit dependency-update review process. Review source changes before advancing the pinned version.

  4. Require SOLANA_PRIVATE_KEY only when live execution actually needs it. Do not inject it into dry-run, configuration-display, or position-display processes unless required by verified SDK behavior.

  5. Run the Skill with a dedicated account, restricted filesystem access, outbound-network allowlisting, and narrowly scoped trading credentials.

  6. Rotate credentials promptly if dependency integrity is ever uncertain, and configure server-side transaction and spending limits where supported.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill description understates operational capabilities: it can perform live trading, discover/import markets, manage positions, and relies on additional credentials and integrations not fully declared up front. This mismatch is dangerous because users or automated systems may approve or run the skill with an incomplete understanding of its authority, financial impact, and secret requirements.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Declaring access to a private signing key is a sensitive capability, and here it is not justified by the stated Kalshi race-momentum trading purpose. In an automated agent context, unjustified private-key access is dangerous because it enables unauthorized signing, fund movement, or secret theft if the skill code behaves unexpectedly or maliciously.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill declares access to sensitive environment variables but does not define any explicit tool scope or permissions boundary. In a trading skill, undeclared env access is risky because it can expose high-value credentials like SIMMER_API_KEY and SOLANA_PRIVATE_KEY to code paths or integrations the user did not explicitly approve.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation conflicts on required credentials: metadata says only SIMMER_API_KEY is required, while later sections also require SOLANA_PRIVATE_KEY for live trading. In a financial trading context, such inconsistency can cause unsafe deployment, accidental secret exposure, or users enabling live mode without realizing an additional private key is involved.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The manifest requests a SOLANA_PRIVATE_KEY even though the skill description only mentions Kalshi F1 championship trading and the declared Python dependency is unrelated to Solana. Unnecessary access to a private key materially expands the blast radius: if the entrypoint or any dependency is compromised, the agent could exfiltrate or misuse blockchain funds without any legitimate business need.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest combines automated execution with access to sensitive credentials but provides no warning or disclosure to the user about private-key risk, automated trade behavior, or possible financial consequences. That omission increases the chance users will provide powerful secrets without understanding that the skill can act unattended and potentially expose both exchange and wallet assets.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest says the skill requires SIMMER_API_KEY and simmer-sdk, suggesting a narrow dependency surface. The file-level documentation and live mode indicate real trades execute via DFlow/Solana and require SOLANA_PRIVATE_KEY, which is a materially broader operational requirement than the manifest states.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest description says the skill trades F1 championship markets using recent race results weighted by recency, implying strategy inputs are based on current race data. In code, both RECENT_RESULTS and BASE_PROBABILITIES are static hard-coded tables, so the skill does not fetch or update recent results and instead trades from embedded assumptions that may become stale.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

In live mode, the skill can place real buy and sell orders immediately based solely on command-line flags and environment-provided credentials, with no interactive confirmation, approval gate, or secondary safety check. In a trading skill handling real funds, this materially increases the chance of accidental or unintended execution, especially when run by automation, cron, or another agent.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The manifest frames the skill as a Kalshi momentum trader, but the code optionally imports and writes trade activity to a separate tradejournal integration. This adds a side-channel for recording trade metadata that is not disclosed as part of the skill's purpose.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
75% confidence
Finding

The stated purpose is to trade F1 championship markets based on momentum, but the code also includes a configuration-management capability that loads and updates persistent config values. While operationally useful, local config mutation is not described in the manifest and is not central to the stated trading intent.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.