Back to skill

Security audit

Polymarket News Events

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed automated trading skill, but its live-trading path has enough safety and scoping gaps that users should review it carefully before installing.

Install only after reviewing and constraining live trading. Use dry-run first, pin dependencies, remove or replace plaintext HTTP feeds, require a second live-trading confirmation, scope SIMMER_API_KEY to minimal funds and permissions, and store state in a private per-user directory.

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)

T09 · Insecure Skill Coding Practices

Error
Location
news_events.py:40
Finding
Trading Safety Checks Fail Open When Market Context Is Unavailable<![CDATA[ ## Vulnerability Details **File Location**: `news_events.py`, lines 40-59; approval is consumed at lines 449-452 **Vulnerability Type**: Fail-open financial transaction control **Risk Level**: High ### Vulnerable Code ```python def check_context(client, market_id, my_probability=None): """Check market context before trading (flip-flop, slippage, edge).""" try: params = {} if my_probability is not None: params["my_probability"] = my_probability ctx = client.get_market_context(market_id, **params) trading = ctx.get("trading", {}) flip_flop = trading.get("flip_flop_warning") if flip_flop and "SEVERE" in flip_flop: return False, f"flip-flop: {flip_flop}" slippage = ctx.get("slippage", {}) if slippage.get("slippage_pct", 0) > 0.15: return False, "slippage too high" edge = ctx.get("edge_analysis", {}) if edge.get("recommendation") == "HOLD": return False, "edge below threshold" return True, "ok" except Exception: return True, "context unavailable" ``` The returned approval is used as follows: ```python ok, reason = check_context(client, market_id) if not ok: log.warning("Skipping trade: %s", reason) continue ``` ### Technical Analysis `check_context()` is intended to enforce pre-trade safeguards covering severe flip-flop warnings, excessive slippage, and insufficient market edge. However, every exception—including network timeouts, authentication errors, SDK failures, malformed responses, and unexpected response types—is converted into an affirmative trading decision. This is a fail-open security design. The absence of validated safety information is treated as equivalent to successful validation. In live mode, execution can consequently continue to `client.trade(...)` while all contextual risk controls are unavailable. The broad `except Exception` also suppresses the underlying error and ...[truncated 1111 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Fail closed whenever market context cannot be validated: ```python except Exception as exc: log.warning("Unable to validate market context: %s", exc) return False, "context unavailable" ``` - Catch specific SDK, timeout, parsing, and authentication exceptions rather than suppressing every exception. - Apply bounded retries with exponential backoff for transient failures. - Require a complete, schema-validated context response before live trading. - Reject missing or nonnumeric slippage values rather than silently treating them as zero. - Add an explicit operator-controlled emergency override if fail-open behavior is ever required; it should not be the default. - Record failed checks in audit logs without exposing credentials or other sensitive values. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
news_events.py:99
Finding
Plaintext HTTP RSS Input Can Influence Automated Live Trades<![CDATA[ ## Vulnerability Details **File Location**: `news_events.py`, line 99; feed processing occurs at lines 184-226 and trading at lines 453-471 **Vulnerability Type**: Unauthenticated network input used for financial decisions **Risk Level**: High ### Vulnerable Code ```python "cnn_top": {"url": "http://rss.cnn.com/rss/edition.rss", "tier": 2}, ``` The untrusted feed content enters the trading pipeline here: ```python feed = feedparser.parse(config["url"]) for entry in feed.entries[:10]: # latest 10 per feed title = entry.get("title", "").strip() link = entry.get("link", "") summary = entry.get("summary", "")[:300] ``` Live orders may subsequently be submitted based on the parsed title and summary: ```python if live: try: result = client.trade( market_id=market_id, side=side, amount=trade_size, source=TRADE_SOURCE, skill_slug=SKILL_SLUG, reasoning=reasoning, ) ``` ### Technical Analysis The CNN RSS source uses plaintext HTTP rather than HTTPS. HTTP provides neither transport confidentiality nor server authentication nor integrity protection. Anyone capable of intercepting or modifying traffic between the Skill and the feed endpoint can alter the returned RSS document. RSS titles and summaries are security-sensitive inputs in this application. They determine whether a story passes filtering, which topics are selected, the estimated impact, market relevance, and trade direction. The modified content can therefore cross directly from unauthenticated network input into a real-money transaction decision. The feed is assigned credibility tier 2, and carefully chosen high-signal keywords and topic terms can satisfy the configured impact threshold. ### Attack Path 1. The Skill requests `http://rss.cnn.com/rss/edition.rss`. 2. An on-path attacker intercepts the plaintext HTTP request or response. 3. The attacker returns a syntactically valid RSS doc ...[truncated 1000 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Replace the HTTP URL with an authenticated HTTPS endpoint. - Configure the HTTP client to reject redirects from HTTPS to HTTP. - Validate the final redirect destination and permit only expected feed hosts. - Set explicit connection and read timeouts. - Consider fetching feeds through a client configuration that enforces TLS certificate validation and response-size limits. - Do not execute a live trade solely from one feed. Require corroboration from multiple independently authenticated sources for high-impact signals. - Add feed provenance to the decision process and reject data from sources whose transport security cannot be verified. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
news_events.py:66
Finding
Predictable Shared Temporary State File Is Vulnerable to Symlink and State Manipulation Attacks<![CDATA[ ## Vulnerability Details **File Location**: `news_events.py`, lines 66-67 and 157-181 **Vulnerability Type**: Unsafe temporary-file handling **Risk Level**: Medium ### Vulnerable Code ```python # State file to avoid re-trading same story STATE_FILE = "/tmp/polymarket_news_seen.json" ``` ```python def load_seen() -> set: try: with open(STATE_FILE, "r") as f: data = json.load(f) # Prune entries older than 24h cutoff = (datetime.now(timezone.utc) - timedelta(hours=24)).isoformat() return {k for k, v in data.items() if v > cutoff} except (FileNotFoundError, json.JSONDecodeError): return set() def save_seen(seen: set): now = datetime.now(timezone.utc).isoformat() data = {h: now for h in seen} try: with open(STATE_FILE, "w") as f: json.dump(data, f) except Exception: pass ``` ### Technical Analysis The Skill stores transaction-deduplication state at a fixed, publicly predictable path in the shared `/tmp` directory. It opens this path using ordinary file operations without: - checking ownership or file type; - preventing symbolic-link traversal; - securely creating the file; - enforcing restrictive permissions; - using atomic replacement; - locking against concurrent executions. A local user can pre-create or replace the path. Because `open(..., "w")` follows symbolic links and truncates the destination, the Skill can be induced to overwrite another file writable by its process identity. A local attacker can also replace or corrupt the JSON state to alter which stories are considered previously processed. The broad exception suppression in `save_seen()` hides failed or manipulated state writes, making detection difficult. ### Attack Path **State manipulation path:** 1. A local attacker writes chosen JSON data to `/tmp/polymarket_news_seen.json`. 2. The Skill loads the attacker-controlled hashes and timestamps. 3. Legitimate stories ...[truncated 1063 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Store state in a private per-user application data directory rather than shared `/tmp`. - Create the directory with mode `0700` and the state file with mode `0600`. - Open files with `O_NOFOLLOW` where supported and verify that the file is a regular file owned by the expected user. - Write to a securely created temporary file in the same private directory, flush and synchronize it, then atomically replace the state file with `os.replace()`. - Use file locking or another concurrency-safe state mechanism because the configured cron schedule may overlap if a run is delayed. - Validate loaded JSON as a dictionary whose keys and values conform to expected hash and timestamp formats. - Log state failures clearly instead of silently suppressing every exception. ]]>

T08 · Insecure Dependencies

Warning
Location
clawhub.json:4
Finding
Security-Critical Python Dependencies Are Unpinned and Lack Integrity Verification<![CDATA[ ## Vulnerability Details **File Location**: `clawhub.json`, lines 4-9 **Vulnerability Type**: Unpinned third-party executable dependencies **Risk Level**: Medium ### Vulnerable Code ```json "requires": { "pip": [ "simmer-sdk", "requests", "feedparser" ], ``` ### Technical Analysis The project declares Python dependencies by package name only. It does not pin exact reviewed versions or provide cryptographic hashes. Consequently, installation behavior can change over time and may retrieve a compromised, malicious, or incompatible future release. The risk is particularly significant for `simmer-sdk`. The Skill supplies this package with `SIMMER_API_KEY`, uses it to query market information, and invokes it to submit live trades. Python packages execute code during import and may also execute build or installation hooks, so a compromised dependency can act with the full privileges of the Skill process. The audit did not establish that any currently published dependency is malicious. The confirmed issue is the absence of version and integrity controls around security-critical executable components. ### Attack Path 1. An attacker compromises an upstream package release, package-maintainer account, distribution artifact, or package-index delivery path. 2. A deployment installs dependencies using the unpinned package names. 3. The resolver selects the attacker-controlled or unexpectedly modified release. 4. Malicious package code runs during installation or import. 5. For `simmer-sdk`, package code can access the supplied API key and intercept, alter, or create trading operations. 6. The code runs with the operating-system and network privileges of the Skill process. ### Impact Assessment A compromised dependency could read environment variables, including `SIMMER_API_KEY`; access files available to the Skill account; make arbitrary outbound requests; falsify market data; or submit unauthorized trades. The maximum scope is the full pr ...[truncated 287 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Pin every dependency to an exact, reviewed version. - Generate and commit a lock file appropriate to the deployment process. - Require cryptographic hashes for downloaded distributions, such as with pip's `--require-hashes`. - Prefer vetted wheels from a controlled package repository and disable unexpected source builds. - Review package ownership, provenance, release history, and transitive dependencies. - Run dependency vulnerability and integrity scanning in CI and before deployment. - Isolate the Skill in a dedicated environment with minimal filesystem and network permissions. - Scope the trading API key to the minimum account, venue, balance, and transaction permissions supported by the service. - Rotate the API key promptly if dependency compromise is suspected. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill advertises capabilities that imply access to environment variables, local file operations, and network resources, but it does not declare any explicit tool scope or permission boundaries in the manifest. For an automated trading skill that consumes external feeds and can be switched to live execution, this omission increases the risk of over-privileged execution, unintended data exposure such as SIMMER_API_KEY access, and unsafe network or file behavior without clear operator review.

External Transmission

Medium
Category
Data Exfiltration
Content
"cnbc_top": {"url": "https://search.cnbc.com/rs/search/combinedcms/view.xml?partnerId=wrss01&id=100003114", "tier": 2},
    "marketwatch": {"url": "https://feeds.marketwatch.com/marketwatch/topstories/", "tier": 2},
    "politico": {"url": "https://www.politico.com/rss/politicopicks.xml", "tier": 2},
    "axios": {"url": "https://api.axios.com/feed/", "tier": 2},
    "thehill": {"url": "https://thehill.com/feed/", "tier": 2},
    "ft": {"url": "https://www.ft.com/rss/home", "tier": 2},
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill can place live trades when invoked with --live, but it does not present a clear, explicit runtime confirmation or prominent user-facing warning immediately before execution. In a trading skill, this increases the risk of accidental real-money orders from operator error, automation misuse, or misunderstanding of the mode, especially because the same code path supports both dry-run and live execution.

Static analysis

No suspicious patterns detected.