Back to skill

Security audit

Polymarket Trader

Security checks for vulnerabilities and agentic risk

Overview

This skill openly places Polymarket trades, but it gives an agent direct wallet-backed trading authority with weak validation and an unsafe shell command wrapper.

Install only if you are comfortable giving the skill live Polymarket trading authority. Use a minimally funded dedicated wallet, review each requested trade yourself, and avoid untrusted market_slug or direction inputs until the shell invocation, local order validation, explicit confirmation, and order-size limits are fixed.

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
SKILL.md:23
Finding
Shell Injection Through Unsafely Interpolated Tool Arguments<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 23–29 **Vulnerability Type**: Command injection through shell-interpolated user input **Risk Level**: High ### Vulnerable Code ```yaml exec: # This command chain securely passes arguments as environment variables to the script # after activating the virtual environment. This prevents shell injection vulnerabilities. command: > source ../../polymarket_venv/bin/activate && export MARKET_SLUG='{{market_slug}}' && export DIRECTION='{{direction}}' && export PRICE={{price}} && export SIZE={{size}} && python trade.py ``` ### Technical Analysis Tool arguments are interpolated directly into a command interpreted by a shell. Assigning values to environment variables does not prevent command injection when those assignments are themselves assembled as shell source code. `market_slug` and `direction` are enclosed in single quotes, but an input containing a single quote can terminate the quoted value and introduce shell operators or additional commands. `price` and `size` are interpolated without any shell quoting. Although those fields are declared as numbers, the command remains dependent on the surrounding tool framework enforcing that type before interpolation. This behavior directly contradicts the comment claiming that environment-variable use prevents shell injection. No strict allowlist, shell escaping mechanism, or argument-array execution boundary is present in the supplied configuration. ### Attack Path 1. An attacker or untrusted caller supplies a crafted `market_slug` or `direction` containing a quote followed by shell syntax. 2. The template engine substitutes that input directly into the `command` string. 3. The injected quote terminates the intended environment-variable value. 4. The shell interprets the remaining text as operators and commands. 5. The injected command runs with the same operating-system identity, filesystem access, environment, an ...[truncated 928 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not construct a shell command by interpolating tool arguments. 2. Invoke `trade.py` through an executable-and-argument array that bypasses shell parsing. 3. Use the platform's structured environment map to pass `MARKET_SLUG`, `DIRECTION`, `PRICE`, and `SIZE` without embedding their values in shell source code. 4. Replace virtual-environment activation with a direct invocation of the virtual environment's interpreter, for example through an execution structure equivalent to: ```text executable: ../../polymarket_venv/bin/python arguments: [trade.py] environment: MARKET_SLUG: <structured market_slug value> DIRECTION: <structured direction value> PRICE: <structured price value> SIZE: <structured size value> ``` 5. Enforce an allowlist for `direction`, strict numeric schemas for `price` and `size`, and a conservative character/length policy for market slugs before process invocation. 6. Do not rely solely on shell escaping. If a shell is unavoidable, use a trusted escaping API and reject values outside the expected grammar. 7. Run the Skill under a restricted account with minimal filesystem and network permissions. 8. Use a dedicated, minimally funded wallet so compromise of the process environment has limited financial impact. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
trade.py:63
Finding
Insufficient Order Validation and Incorrect Side Selection for the No Outcome<![CDATA[ ## Vulnerability Details **File Location**: `trade.py`, lines 63–70 and 101–110 **Vulnerability Type**: Unsafe financial-operation validation and incorrect order semantics **Risk Level**: Medium ### Vulnerable Code ```python if direction.lower() == 'yes': token_id = token_ids[0] order_side = BUY elif direction.lower() == 'no': token_id = token_ids[1] order_side = SELL else: return {"error": "Invalid direction. Must be 'Yes' or 'No'."} ``` ```python try: price = float(price_str) size = float(size_str) except ValueError: print("Error: PRICE and SIZE must be valid numbers.") exit(1) result = place_order(slug, direction, price, size) ``` ### Technical Analysis The declared interface states that `price` must be between `0.01` and `0.99`, but the implementation only converts it to a floating-point value. It does not enforce the documented range. Likewise, `size` is not required to be positive or bounded. Python's `float()` conversion also accepts special non-finite values such as `nan` and `inf`. Consequently, the script may pass negative, zero, out-of-range, or non-finite values to the order-building library. The remote service or dependency may reject some such values, but remote rejection is not a substitute for local validation before creating and signing a financial order. The outcome mapping also selects `SELL` when the caller requests `No`. Buying a No outcome normally requires selecting the No token and submitting a `BUY` order. Selling the No token is a materially different financial operation and may reduce an existing position rather than place the bet described by the Skill interface. The implementation additionally assumes that the first two token identifiers always correspond to Yes and No without validating the market's outcome metadata. ### Attack Path 1. A caller supplies an out-of-range, negative, excessive, or non-finite price or size. 2. `float()` accepts the value where syntactically supp ...[truncated 1410 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate all financial parameters locally before initializing credentials or signing an order: ```python import math if not math.isfinite(price) or not 0.01 <= price <= 0.99: return {"error": "PRICE must be finite and between 0.01 and 0.99."} if not math.isfinite(size) or size <= 0: return {"error": "SIZE must be a positive finite number."} ``` 2. Add a configurable maximum size and maximum notional order value. 3. Require explicit confirmation for orders above a conservative threshold. 4. Map both requested outcomes to the intended operation. If the interface means “buy shares in this outcome,” use `BUY` for the selected Yes or No token. 5. If selling is required, expose it as a separate, explicit `side` parameter rather than overloading the outcome direction. 6. Validate the market response's outcome labels and associate token identifiers by label instead of assuming index zero is Yes and index one is No. 7. Confirm that the market returned by the API exactly matches the requested slug and is active and tradable. 8. Use fixed-point decimal handling where supported to avoid floating-point ambiguity in financial values. 9. Return structured errors without including sensitive client or signing-library details. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (2)

Context-Inappropriate Capability

High
Confidence
95% confidence
Finding
The code reads a live Polymarket private key from an environment variable, derives API credentials, and initializes a client capable of submitting authenticated market orders. In an agent skill of unknown purpose, this grants direct financial transaction capability and exposes sensitive signing material to any workflow that can invoke the skill, making unauthorized or unintended trades possible.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The skill makes outbound requests to Polymarket APIs to resolve market data and then uses that data to support order placement, creating an external action path with real-world financial effect. Because the skill has no declared scope, approval gate, or destination restrictions beyond hardcoded endpoints, it increases the risk of unauthorized network-driven trading activity.

Static analysis

No suspicious patterns detected.