Back to skill

Security audit

Polymarket Micro Weather Sniper Trader

Security checks for vulnerabilities and agentic risk

Overview

This trading skill is not malicious, but it needs review because its live-trading safeguards and forecast-source disclosure do not fully match the code.

Install only if you are comfortable reviewing a live-trading skill carefully. Use paper mode first, use a least-privilege SIMMER_API_KEY with server-side trade and balance limits, pin or vet simmer-sdk before deployment, and do not enable live mode until the wttr.in fallback and the documented risk controls are either fixed or explicitly accepted.

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

T08 · Insecure Dependencies

Warning
Location
clawhub.json:7
Finding

Unpinned Privileged Trading Dependency

Content
View full analysis
Remediation
View remediation
``` 3. Install packages with hash enforcement where supported: ```bash pip install --require-hashes -r requirements.txt ``` 4. Review package ownership, release provenance, signatures, and dependency changes before updating the pinned version. 5. Execute the Skill in a restricted environment containing only the required API key and no unrelated credentials. 6. Apply server-side trading limits so dependency compromise cannot result in unrestricted financial exposure. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:330
Finding

Configured Minimum-Days Trading Safeguard Is Not Enforced

Content
View full analysis
= MAX_POSITIONS: break city = parsed["city"] if city not in forecasts: continue date_key = forecast_date_key(parsed) if not date_key or date_key not in forecasts[city]: continue ``` The setting is read and reloaded: ```python MIN_DAYS = int(os.environ.get("SIMMER_MIN_DAYS", "0")) ``` ```python MIN_DAYS = int(os.environ.get("SIMMER_MIN_DAYS", str(MIN_DAYS))) ``` However, no comparison between the market date and `MIN_DAYS` occurs before `client.trade(...)`. ### Technical Analysis `SIMMER_MIN_DAYS` is documented and exposed as a risk parameter intended to prevent trades too close to resolution. Although the code reads this setting, it never calculates the number of days until the market date or rejects a market that falls below the configured minimum. This creates a fail-open safeguard: operators can configure a nonzero minimum and receive no error or warning that the setting is ineffective. A market remains eligible as long as its date can be parsed and is present in the weather forecast. ### Attack Path 1. An operator configures `SIMMER_MIN_DAYS` to exclude same-day or near-resolution markets. 2. The Skill discovers a qualifying weather market whose date is present in the forecast data. 3. The trading loop verifies only the existence of `date_key`; it does not compare the date with `MIN_DAYS`. 4. The normal signal and spread conditions are satisfied. 5. `client.trade(...)` submits the trade despite the configured minimum-days restriction. 6. If `--live` is enabled, the violation affects a real-money p ...[truncated 474 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:330
Finding

Maximum Concurrent Positions Limit Only Counts Trades in the Current Run

Content
View full analysis
= MAX_POSITIONS: break ``` The counter increases only for successful trades in the current invocation: ```python if r.success: placed += 1 elif "trade limit" in str(r.error).lower(): safe_print(" [stop] Daily trade limit reached.") break ``` ### Technical Analysis The setting is described as a maximum number of concurrent positions, but the implementation is only a per-process successful-trade counter. `placed` is reset to zero each time `run()` executes. The code does not: - Retrieve existing open positions. - Count positions created by previous runs. - Detect an existing position in the same market. - Calculate remaining capacity from the configured concurrent-position limit. Consequently, repeated execution can accumulate substantially more exposure than `MAX_POSITIONS` suggests. ### Attack Path 1. The account already has open positions, or the Skill completes an initial run and opens up to `MAX_POSITIONS` positions. 2. The Skill is executed again manually or through a separately configured automation. 3. `placed` resets to zero. 4. Existing positions are not queried or included in the limit. 5. The Skill submits up to `MAX_POSITIONS` additional successful trades. 6. Repeated runs continue accumulating positions beyond the declared concurrent maximum. ### Impact Assessment The issue does not create operating-system privilege escalation. It affects account-level financial exposure. Repeated live runs can exceed the operator's intended number of open positions, duplicate exposure in the same market, increase correlated weather risk, and consume more capital than expected. The ultimate scope is bounded ...[truncated 121 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
trader.py:345
Finding

Trade Amount Can Exceed the Configured Maximum Position

Content
View full analysis
= NO_THRESHOLD: # NOAA says NO and market is overpriced — SELL NO edge = p - (1 - NOAA_ACCURACY) conviction = min(1.0, edge / NOAA_ACCURACY) size = max(MIN_TRADE, round(conviction * MAX_POSITION, 2)) ``` The manifest independently permits: - `SIMMER_MAX_POSITION` values from `1` to `50`. - `SIMMER_MIN_TRADE` values from `1` to `20`. It does not require `SIMMER_MIN_TRADE <= SIMMER_MAX_POSITION`. ### Technical Analysis The amount calculation treats `MIN_TRADE` as an unconditional floor: ```python max(MIN_TRADE, calculated_amount) ``` If `MIN_TRADE` is greater than `MAX_POSITION`, the floor wins and the final trade amount exceeds the stated maximum position. For example, a maximum position of `$5` and minimum trade of `$20` produces a `$20` trade. The implementation performs no cross-field validation after reading values from the environment or applying Skill configuration. Direct environment values are also not constrained to the manifest ranges. This means malformed, negative, non-finite, or logically inconsistent settings may reach financial calculations. ### Attack Path 1. Configuration sets `SIMMER_MIN_TRADE` above `SIMMER_MAX_POS ...[truncated 843 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The documented behavior says the strategy relies on NOAA and Open-Meteo, but the finding indicates the implementation may also use an undeclared third-party source and may not actually combine both sources as claimed. In a live trading context, this is dangerous because users may trust the strategy's stated data provenance and robustness while trades are actually driven by a different or weaker source chain, increasing model risk, manipulation exposure, and undisclosed data exfiltration to third parties.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill declares access to sensitive capabilities in practice (environment variables and outbound network use) but does not explicitly scope or disclose those permissions. In a trading skill that uses a high-value API key and external data sources, missing tool/permission declarations reduce transparency and make it harder for operators or policy systems to constrain what the skill can access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest declares use of a sensitive API credential and configures an automated trading entrypoint, but it provides no user-facing disclosure about credential access, trading authority, or the fact that the skill can autonomously place trades. In a trading skill, this increases the risk of users granting powerful credentials without understanding that funds or positions may be affected automatically.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation states the strategy uses NOAA forecasts as its edge, but the implementation trades on Open-Meteo and wttr.in whenever NOAA is unavailable. This discrepancy can mislead users about the provenance and reliability of the signal driving real-money trades, undermining informed consent and risk management.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill advertises NOAA and Open-Meteo as its forecasting basis but silently falls back to wttr.in, an undeclared third-party data source. In an automated trading skill, hidden provider substitution changes the trust boundary and can cause trades to be made on lower-quality or unexpected data without operator awareness.

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 · trader.py (reported line 131)May include surrounding context.

python
def _try_noaa(info: dict, city: str) -> dict[str, int]:
    headers = {"User-Agent": "kladde-weather-agent/1.0 (diagnostikon)", "Accept": "application/json"}
    try:
        req = Request(f"https://api.weather.gov/points/{info['lat']},{info['lon']}", headers=headers)
        with urlopen(req, timeout=10) as r:
            points = json.loads(r.read())
        forecast_url = points["properties"]["forecast"]

External Transmission

Medium
Category
Data Exfiltration
Confidence
83% confidence
Finding

This outbound call sends market-driving requests to Open-Meteo, a third-party service not emphasized in the core strategy description, and its results can directly trigger trades. While not data exfiltration in the classic sense, it expands the external trust boundary for an automated trading agent and can materially affect behavior if the provider is unavailable, manipulated, or lower quality than expected.

Content

Scanner excerpt · trader.py (reported line 151)May include surrounding context.

python
def _try_open_meteo(info: dict, city: str) -> dict[str, int]:
    try:
        unit_param = "fahrenheit" if info["unit"] == "F" else "celsius"
        url = (f"https://api.open-meteo.com/v1/forecast?"
               f"latitude={info['lat']}&longitude={info['lon']}"
               f"&daily=temperature_2m_max&temperature_unit={unit_param}"
               f"&forecast_days=7")

Static analysis

No suspicious patterns detected.