Back to skill

Security audit

Polymarket Weather Trader

Security checks for vulnerabilities and agentic risk

Overview

This is a real weather-market trading skill, but it deserves review because it can place financial trades with a Simmer API key and its credential handling is not tightly guarded.

Review before installing if the Simmer API key can trade or access significant account data. Use dry-run first, keep small max-position and max-trades limits, avoid --no-safeguards and unattended quiet cron runs until you trust the strategy, and prefer a narrowly scoped or separate API key if Simmer supports it.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
status.py:25
Finding
Bearer API token may be disclosed through cross-origin redirects in the status client<![CDATA[ ## Vulnerability Details **File Location**: `status.py`, lines 25–34 **Vulnerability Type**: Authenticated cross-origin redirect / credential disclosure **Risk Level**: High ### Vulnerable Code ```python def api_request(api_key: str, endpoint: str) -> dict: """Make authenticated request to Simmer API.""" url = f"{SIMMER_API_BASE}{endpoint}" req = Request(url, headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }) try: with urlopen(req, timeout=30) as resp: return json.loads(resp.read().decode()) ``` ### Technical Analysis The function places the sensitive `SIMMER_API_KEY` in an `Authorization: Bearer` header and passes the request to `urllib.request.urlopen`. Python's default redirect handler follows supported HTTP redirects. The code neither rejects redirects nor verifies that a redirect destination remains on the expected `api.simmer.markets` origin. Request headers can consequently be propagated when constructing a redirected request, including to a different HTTPS origin. If the trusted endpoint or its supporting infrastructure returns a malicious cross-origin redirect, the bearer credential may be sent to the redirect target. Sending the token to the documented Simmer API is necessary for the declared account-status functionality. Allowing that credential to follow redirects to an unrestricted origin exceeds the minimum network privilege required. Exploitation depends on an attacker being able to influence the trusted API's redirect response, such as through API compromise, infrastructure compromise, or a redirect vulnerability. TLS prevents an ordinary passive network observer from simply injecting such a redirect. ### Attack Path 1. The user configures a valid `SIMMER_API_KEY` and runs `status.py`. 2. The script requests a Simmer portfolio or positions endpoint with the bearer token. 3. An attacker-controlled or compromised endpoint returns an HTTP r ...[truncated 917 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable automatic redirect handling for authenticated requests and treat redirects as errors unless explicitly required. 2. If redirects are operationally necessary, validate every redirect before following it: - Require the `https` scheme. - Require the normalized hostname to be exactly `api.simmer.markets`. - Reject user-info, unexpected ports, and hostname suffix tricks. 3. Remove the `Authorization` header whenever the scheme, hostname, or effective port changes. 4. Apply the same hardened request helper to every authenticated Simmer API operation. 5. Use narrowly scoped and revocable API keys. A status-only client should use a read-only key when the service supports one. 6. Avoid returning or logging credentials in exception messages, diagnostics, or response bodies. 7. Add automated tests covering same-origin redirects, cross-origin redirects, protocol downgrades, and malformed redirect targets. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
weather_trader.py:334
Finding
Trading API bearer token may be disclosed through cross-origin redirects<![CDATA[ ## Vulnerability Details **File Location**: `weather_trader.py`, lines 334–349 **Vulnerability Type**: Authenticated cross-origin redirect / credential disclosure **Risk Level**: High ### Vulnerable Code ```python def sdk_request(api_key: str, method: str, endpoint: str, data: dict = None) -> dict: """Make authenticated request to Simmer SDK.""" url = f"{SIMMER_API_BASE}{endpoint}" headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", } try: if method == "GET": req = Request(url, headers=headers) else: body = json.dumps(data).encode() if data else None req = Request(url, data=body, headers=headers, method=method) with urlopen(req, timeout=30) as response: return json.loads(response.read().decode()) ``` ### Technical Analysis The common SDK request function attaches `SIMMER_API_KEY` as a bearer credential and relies on the default redirect behavior of `urllib.request.urlopen`. It does not constrain redirect targets to the intended Simmer API origin and does not explicitly strip authentication data when the origin changes. This function supports both account-information requests and privileged trading operations. It is called for portfolio, positions, market context, price history, risk-monitor management, and trade execution. The credential is therefore likely intended to possess financially sensitive permissions. The initial transmission of the token to `https://api.simmer.markets` is required by the declared Skill functionality. Permitting automatic propagation toward an unvalidated redirect destination is unnecessary and violates least-privilege network handling. The issue does not indicate deliberate exfiltration. Exploitation requires control over a redirect response from the trusted request path, such as through compromise of the API or its infrastructure, or an exploitable open-redirect condition. ...[truncated 1298 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace unrestricted `urlopen` redirect handling with a hardened authenticated HTTP helper. 2. Reject redirects by default for API calls, particularly trade and account-state mutations. 3. If same-origin redirects must be supported: - Resolve the redirect target safely. - Require `https`. - Require the exact hostname `api.simmer.markets`. - Require the expected port. - Reject origin changes and protocol downgrades. 4. Strip `Authorization` and other sensitive headers before following any redirect that is not demonstrably same-origin. 5. Consider treating all redirects for non-GET methods as failures to avoid unexpected replay or transformation of trade requests. 6. Use separate least-privilege credentials for read-only analysis and live trading where supported. 7. Add server-side transaction limits and require narrowly scoped, short-lived, revocable tokens. 8. Add regression tests proving that bearer credentials are never sent to cross-origin redirect destinations. ]]>
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 (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description centers on weather-market trading automation using NOAA forecasts and a specific trading strategy. The supplied code does none of that. It only performs authenticated GET requests to Simmer portfolio and positions endpoints to display account status information. There is no forecast retrieval, no market selection, no trading logic, no order submission, and no automation of bets. While it does use the Simmer API, its primary purpose is materially different: portfolio monitoring rather than weather-market trading.

Missing User Warnings

High
Confidence
97% confidence
Finding
The skill provides commands for live trading, disabling safeguards, and quiet execution, but it does not prominently warn users about real-money loss, market risk, automation risk, or the consequences of bypassing protections. In the context of a trading skill, missing explicit risk disclosure makes accidental or poorly informed financial actions more likely and therefore materially increases harm potential.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill declares access to environment variables and describes commands that interact with local scripts and remote APIs, but it does not define any explicit tool/permission scope. In an agent setting, missing scope boundaries can allow the skill to be invoked with broader-than-expected file, network, or secret access, increasing the chance of unintended API use or credential exposure.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The invocation text is broad enough to match ordinary weather-related requests, not just explicit trading intents. In an agent environment, that can cause an automated trading skill to activate during benign weather queries, creating a path to accidental financial actions or unnecessary exposure of trading/account context.

Missing User Warnings

Low
Confidence
85% confidence
Finding
The update_config function writes configuration values to config.json on disk, which is a file-modifying operation. Although the CLI help mentions setting config values, the code lacks an explicit warning or disclosure near the write path that using --set will persist data locally.

Missing User Warnings

Low
Confidence
79% confidence
Finding
This code reads the SIMMER_API_KEY credential from the environment and exits if it is missing, but it does not include any user-facing warning or comment about the sensitivity of the credential beyond stating that it is required. Under the code-file warning criteria, access to sensitive environment variables should have some disclosure unless clearly covered elsewhere in the skill description.

Static analysis

No suspicious patterns detected.