Back to skill

Security audit

Kalshi Fed Data Reaction Trader

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed dry-run-by-default trading skill, but live mode uses high-value credentials and has safeguards that are too broad or fail open for real-money trading.

Review carefully before installing. Use paper or dry-run mode unless you have audited the SDK and strategy, provide only restricted trading credentials, use an isolated low-balance wallet if a Solana key is required, and do not run --live or automations until safeguard failures block trades and exit logic is limited to positions created by this skill.

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
trader.py:320
Finding

Trading safeguards fail open when market context retrieval fails

Content
View full analysis
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, [] ``` The returned approval is subsequently used to authorize a trade: ```python ctx = get_market_context( market_id, my_probability=fair_cut_p if side == "yes" else 1 - fair_cut_p ) ok, reasons = check_safeguards(ctx) if not ok: log(f" Skipped: {'; '.join(reasons)}") skip_reasons.extend(reasons) continue if not dry_run: result = execute_trade( market_id, side, size, reasoning=(f"Data reaction: regime={regime or 'neutral'} " f"implied_cpi={implied_cpi or 'N/A'} " f"fair={fair_cut_p:.1%} market={price:.1%} edge={edge:+.1%}"), ``` ### Technical Analysis `get_market_context()` suppresses every exception and returns `None`. The safeguard function explicitly interprets missing or empty context as permission to trade by returning `(True, [])`. Consequently, all context-dependent controls are bypassed if the SDK or context endpoint fails. These controls include: - Resolved-market detection - Minimum time-to-resolution enforcement - Liquidity validation - Slippage limits - Severe flip-flop warnings Safety checks controlling financial tra ...[truncated 1427 chars]
Remediation
View remediation
tuple[bool, list[str]]: if not isinstance(context, dict) or not context: return False, ["Market context unavailable or invalid"] ``` 2. Preserve a sanitized diagnostic message instead of silently discarding all exceptions: ```python except Exception as exc: safe_print(f"Context retrieval failed for market {market_id}: {exc}") return None ``` Ensure logs do not expose API keys, authorization headers, or private-key material. 3. Validate the context response schema before trading. Required fields for live trading should include resolution status, time to resolution, liquidity, and applicable slippage estimates. 4. Distinguish dry-run analysis from live authorization. Missing context may be tolerated for displaying an opportunity, but it must never authorize a live transaction. 5. Consider bounded retries with exponential backoff for transient errors. If validation remains unavailable after retries, skip the trade. 6. Add tests proving that `None`, `{}`, malformed context, request exceptions, and missing required fields all prevent live execution. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
trader.py:392
Finding

Exit logic can liquidate positions not opened by this Skill

Content
View full analysis
= EXIT_THRESHOLD: found += 1 log(f" EXIT: {question} price={price:.2f} >= {EXIT_THRESHOLD:.2f}") ctx = get_market_context(market_id) ok, reasons = check_safeguards(ctx) if not ok: log(f" Skipped: {'; '.join(reasons)}") continue if not dry_run: result = execute_trade( market_id, "sell", shares, reasoning=f"Exit: price {price:.2f} >= threshold {EXIT_THRESHOLD:.2f}", ) ``` ### Technical Analysis The source check correctly recognizes positions tagged with this Skill's `TRADE_SOURCE`. However, the Boolean `or` adds every position whose question contains both “rate” and “cut,” regardless of which user workflow or strategy created it. Question text is not an ownership or authorization boundary. It is externally sourced descriptive metadata and does not establish that this Skill is permitted to manage the position. The implementation therefore exceeds the minimum privilege needed for the declared functionality: the Skill only needs to exit its own strategy positions, not all rate-cut positions in the account. ### Attack Path 1. A user or another strategy opens a rate-cut position that is not tagged with `sdk:kalshi-fed-data`. 2. The Skill retrieves all account positions through `/api/sdk/positions`. 3. The unrelated position's question contains the words “rate” and “cut.” 4. The fallback keyword condition classifies the position as one managed by this Skill. 5. Once its current price reaches ` ...[truncated 845 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
clawhub.json:4
Finding

Unpinned third-party SDK executes with access to high-value trading credentials

Content
View full analysis
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 The project specifies `simmer-sdk` by package name only. Installation can therefore resolve to a future release that was not part of this audit. Python package installation and import permit dependency-controlled code to execute locally. The SDK receives `SIMMER_API_KEY`, which the documentation characterizes as trading ...[truncated 1726 chars]
Remediation
View remediation
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 (8)

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Requesting blockchain wallet credentials unrelated to the stated Fed-data/Kalshi trading purpose is a serious secret overreach. In an automated agent context, this creates an unnecessary path for exfiltration or unauthorized transactions, and the mismatch between claimed purpose and requested secret increases suspicion.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
94% confidence
Finding

In live mode, the script can place real trades immediately when invoked with --live, without any interactive confirmation, secondary approval gate, or equivalent explicit acknowledgment. In a trading skill handling real-money actions, this increases the risk of accidental execution from user error, automation misconfiguration, or unintended invocation, leading to financial loss.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill requires high-value environment secrets such as SIMMER_API_KEY and SOLANA_PRIVATE_KEY but does not declare an explicit tool scope or permissions boundary. In an agent ecosystem, this can lead to overbroad secret exposure, where the runtime may provide environment access without clear least-privilege constraints or user visibility.

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 SOLANA_PRIVATE_KEY even though the skill is described as a Kalshi Fed-data trader using SIMMER_API_KEY and simmer-sdk. Requiring an unrelated blockchain private key expands credential exposure and could enable unauthorized wallet access or fund movement if the entrypoint or dependencies misuse that secret.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill is configured for an automated trading entrypoint and requests a private key, but the manifest provides no user-facing warning about financial risk, custody risk, or the consequences of granting key access. This increases the chance that users supply highly sensitive credentials without understanding that the agent may execute irreversible transactions or expose funds if compromised.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest and module docstring state that the trader reacts to macro data releases including CPI and jobs. In code, the signal-generation path computes implied CPI, classifies only CPI regimes, and adjusts fair cut probability solely from that CPI-derived regime; the jobs-related thresholds and labels are defined but never used in trading decisions.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The client is initialized with TRADING_VENUE defaulting to kalshi, binding the skill to a specific platform/market locale unless the environment is manually overridden. This is a natural-language policy concern because the skill does not present the user with an explicit choice or opt-in for that locale/platform constraint in its user-facing behavior.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The usage/help text explicitly describes live mode as executing real trades via DFlow/Solana. However, live trading is performed by calling SimmerClient.trade after initializing a Simmer client with API credentials, and the only direct credential checked for operation is SIMMER_API_KEY in this file.

Content

No source excerpt is available for this finding.