Back to skill

Security audit

Kalshi Crypto Monotonicity Trader

Security checks for vulnerabilities and agentic risk

Overview

This is a real trading skill, but it requests raw wallet/trading credentials too broadly and can make live financial changes through an unpinned SDK dependency.

Install only after reviewing the exact simmer-sdk version and using tightly limited credentials. Prefer a dedicated low-balance wallet, do not expose SOLANA_PRIVATE_KEY for dry-run use, and treat --live as permission for real trades and possible sale of existing BTC/ETH-related positions.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T08 · Insecure Dependencies

Error
Location
clawhub.json:4
Finding

Unpinned Third-Party Dependency Executes with Access to Trading Credentials

Content
View full analysis

Vulnerability Details

File Location: clawhub.json:4-11; related imports and credential use at trader.py:45 and trader.py:206-220
Vulnerability Type: Supply-chain exposure through an unpinned privileged dependency
Risk Level: High

The Skill installs simmer-sdk without a version constraint or integrity hash while injecting high-value trading credentials into the same process.

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

The dependency is imported and entrusted with the API credential:

python
from simmer_sdk.skill import load_config, update_config, get_config_path
python
def get_client(live=True):
    """Lazy-init SimmerClient singleton."""
    global _client
    if _client is None:
        try:
            from simmer_sdk import SimmerClient
        except ImportError:
            print("Error: simmer-sdk not installed. Run: pip install simmer-sdk")
            sys.exit(1)
        api_key = os.environ.get("SIMMER_API_KEY")
        if not api_key:
            print("Error: SIMMER_API_KEY environment variable not set")
            print("Get your API key from: simmer.markets/dashboard -> SDK tab")
            sys.exit(1)
        venue = os.environ.get("TRADING_VENUE", "kalshi")
        _client = SimmerClient(api_key=api_key, venue=venue, live=live)
    return _client

Technical Analysis

An unconstrained package requirement allows different dependency versions to be installed over time without a corresponding change to the audited Skill. Python modules execute code during import, and imported code runs with the permissions and environment of the hosting process.

In this case, the process environment is declared to contain SIMMER_API_KEY and SOLANA_PRIVATE_KEY. The SDK also receives the API key directly when SimmerClient is instantiated. Consequently, compr ...[truncated 1881 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin simmer-sdk to an exact, reviewed version rather than accepting any available release.
  2. Use a lockfile and enforce package hashes, such as pip hash checking with --require-hashes.
  3. Review the precise SDK source corresponding to the pinned artifact, including import-time behavior, network destinations, credential handling, and trade execution.
  4. Verify package provenance and publisher signatures where supported by the distribution channel.
  5. Run the SDK in an isolated process that receives only the minimum credential required for the selected operation.
  6. Do not expose the Solana private key to paper-mode, configuration-only, market-discovery, or position-display processes.
  7. Prefer a narrowly scoped external signing service or wallet adapter over placing a raw wallet private key in the general process environment.
  8. Apply outbound network restrictions so the process can communicate only with explicitly approved trading endpoints.

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
clawhub.json:4
Finding

Solana Private Key Is Required Even When Live Signing Is Unnecessary

Content
View full analysis

Vulnerability Details

File Location: clawhub.json:4-8; documented behavior at SKILL.md:68-72 and SKILL.md:85-91
Vulnerability Type: Excessive credential exposure and violation of least privilege
Risk Level: Medium

The package manifest declares the raw Solana private key as an unconditional environment requirement:

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

The documentation likewise instructs users to provide both credentials despite stating that dry-run mode is the default:

markdown
Requires: `SIMMER_API_KEY` and `SOLANA_PRIVATE_KEY` environment variables.
markdown
**The skill defaults to dry-run mode. Real trades only execute when `--live` is passed explicitly.**

| Scenario | Mode | Financial risk |
|----------|------|----------------|
| `python trader.py` | Dry run | None |
| Cron / automaton | Dry run | None |
| `python trader.py --live` | Live (Kalshi via DFlow) | Real USDC |

Technical Analysis

The reviewed first-party code does not directly read SOLANA_PRIVATE_KEY. Live mode is selected only when the user supplies --live, while ordinary execution initializes the client with live=False. Requiring the private key at package or runtime level for all modes therefore exceeds the minimum privileges needed for dry-run analysis, configuration display, market discovery, and position inspection.

Environment variables are available to Python code running in the same process, including imported dependencies and optional integrations. Supplying a raw signing key before it is operationally needed increases the number of components and execution paths capable of accessing it.

The static pre-scan concern about sensitive network transmission is not confirmed as direct private-key exfiltration by the reviewed first-party code. Nevertheless, unconditional credential injection mate ...[truncated 1237 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove SOLANA_PRIVATE_KEY from unconditional manifest requirements.
  2. Request the signing credential only after the user explicitly selects --live.
  3. Separate execution into low-privilege and live-trading processes. The low-privilege process should perform discovery and analysis without wallet credentials.
  4. Keep configuration display, dry-run operation, position display, and market-data queries entirely free of private-key access.
  5. Prefer an external signer, hardware wallet, or restricted signing service so the raw private key is never exposed to the Python process.
  6. If an environment variable remains necessary, inject it only into the live-trading subprocess immediately before signing and clear that process after completion.
  7. Use a dedicated wallet with limited funds and narrowly scoped authority for this strategy.
  8. Update SKILL.md to clearly distinguish credentials required for dry-run operation from credentials required exclusively for live execution.
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 (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The documented description understates the skill's effective behavior by omitting live-trading dependencies, broader asset coverage, market discovery, and ongoing position management. In a trading skill handling real credentials and funds, this mismatch is dangerous because operators may approve or supply secrets based on an incomplete understanding of what the skill can do, increasing the chance of unintended trades, broader market exposure, or unsafe automation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Access to a blockchain private key is highly sensitive and unjustified by the declared strategy context, making the requirement itself a serious security concern. Because private keys enable irreversible fund movement, any unnecessary exposure creates a path to theft if the agent code, dependencies, or operator environment are abused.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill requests and documents access to sensitive environment variables, including trading credentials, but does not declare any explicit tool scope or permissions boundary. In an agent ecosystem, missing capability declarations reduce transparency and policy enforcement, making it easier for a skill with credential access to be installed or executed with broader privileges than reviewers expect.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest asks for a private key credential without any user-facing disclosure explaining why such sensitive access is needed or what actions it can authorize. This undermines informed consent and increases the chance that users will supply a credential far more powerful than required, enabling severe downstream harm if mishandled.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest requests SOLANA_PRIVATE_KEY even though the stated skill purpose is trading Kalshi crypto monotonicity opportunities, which does not obviously require Solana signing authority. Unnecessary private key access materially increases the blast radius: if the runtime, dependency, or future code path is compromised, the key could be used to drain external assets unrelated to the skill’s advertised function.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The top-level docstring states the strategy should 'buy the cheaper higher-probability contract and sell the overpriced lower one.' However, the implementation identifies the lower-threshold market as underpriced and the higher-threshold market as overpriced, then buys YES on the lower-threshold market and buys NO on the higher-threshold market (L158-L171, L549-L612). This is an active contradiction in the documented trading intent, not just an omitted detail.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation inconsistently states credential requirements, listing only SIMMER_API_KEY in metadata while later requiring SOLANA_PRIVATE_KEY for live trading. Contradictory secret requirements can cause operators to mishandle high-value credentials, misconfigure deployments, or grant unnecessary secret access without understanding when it is actually needed.

Content

No source excerpt is available for this finding.