Back to skill

Security audit

Polymarket Autotrade

Security checks for vulnerabilities and agentic risk

Overview

The skill is a disclosed Polymarket trading CLI, but live trading and credential handling need Review before installation.

Install only if you are comfortable giving this skill a dedicated, limited-funds Polymarket wallet and allowing it to submit trades. Review every trade manually outside the skill, avoid using a main wallet, restrict credential-file permissions, and treat the unpinned trading dependency as a supply-chain risk until the publisher adds confirmation, least-privilege read-only paths, and stronger secret storage.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
skill.py:61
Finding

API Trading Credentials Are Stored Without Restrictive File Permissions

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
skill.py:338
Finding

Public Price Queries Unnecessarily Access the Wallet Private Key and Generate Persistent Credentials

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:2
Finding

Security-Critical Dependencies Are Unbounded and the Trading Client Import Namespace Is Inconsistent

Content
View full analysis
=2.31.0 py-clob-client>=1.5.0 ``` `pyproject.toml`: ```toml dependencies = [ "requests>=2.31.0", "py-clob-client>=1.5.0", ] ``` `skill.py`: ```python try: from py_clob_client_v2 import ClobClient from py_clob_client_v2.clob_types import MarketOrderArgsV2, OrderType, PartialCreateOrderOptions from py_clob_client.order_builder.constants import BUY, SELL except ImportError: print("❌ py-clob-client not installed") print(" Install: pip install py-clob-client") return None ``` ### Technical Analysis Both dependencies use lower-bound-only constraints. A future installation may therefore resolve to any later release, and the project supplies neither a lockfile nor package hashes. This is particularly sensitive for `py-clob-client`, because the code gives the trading client access to the wallet private key and uses it to create and submit financial orders. A compromised future release could execute in the Skill process and access signing material. The implementation also imports its main client and order types from `py_clob_client_v2`, while the declared dependency is `py-clob-client` and constants are imported from `py_clob_client`. The reviewed files do not establish that the declared package reliably supplies the `py_clob_client_v2` namespace. This mismatch can cause runtime failure or encourage installation of an unintended similarly named package. No malicious dependency is embedded in the reviewed project. The vulnerability is the lack of reproducible, verified dependency selection around security-critical code. ### Attack Path 1. A user follows `SKILL.md` and runs `pip install -r requirements.t ...[truncated 1150 chars]
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (21)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · SKILL.md (reported line 99)May include surrounding context.

md
- **Strongly recommended**: Use a **dedicated wallet with limited funds**, NOT your main wallet.
- The private key is **only used locally** for signing transactions via `py-clob-client`. It is **never transmitted** to any endpoint other than `clob.polymarket.com` (Polymarket's official CLOB API).
- If using config file method: `chmod 600 ~/.openclaw/credentials/polymarket.json`

## Commands

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill declares capabilities that require access to environment variables, file writes, and networked trading endpoints, but it does not declare any explicit tool scope or permission boundaries. In a trading skill that handles private keys and can place orders, this increases the chance of over-broad execution and unintended access to sensitive data or state-changing actions.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
94% confidence
Finding

The skill instructs users to persist a wallet private key in a local JSON file under ~/.openclaw/credentials and also caches generated API credentials locally. Persistent storage of high-value secrets materially increases the blast radius of local compromise, accidental backup leakage, or misuse by other tools with filesystem access.

Content

Scanner excerpt · SKILL.md (reported line 79)May include surrounding context.

Method 2: Via config file (Legacy)

Create ~/.openclaw/credentials/polymarket.json:

json
{

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 99)May include surrounding context.

md
- **Strongly recommended**: Use a **dedicated wallet with limited funds**, NOT your main wallet.
- The private key is **only used locally** for signing transactions via `py-clob-client`. It is **never transmitted** to any endpoint other than `clob.polymarket.com` (Polymarket's official CLOB API).
- If using config file method: `chmod 600 ~/.openclaw/credentials/polymarket.json`

## Commands

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trading triggers are broad phrases like '买 2 美元', '下注 5 美元', and 'Long [market]', which can overlap with normal conversational intent and may cause the skill to activate for real-money actions without sufficiently precise user direction. In a financial trading context, ambiguous activation is dangerous because it can lead to unintended order placement or wallet usage.

Content

No source excerpt is available for this finding.

Tainted flow: 'API_CREDS_FILE' from os.environ.get (line 23, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · skill.py (reported line 70)May include surrounding context.

python
}
    
    os.makedirs(os.path.dirname(API_CREDS_FILE), exist_ok=True)
    with open(API_CREDS_FILE, 'w') as f:
        json.dump(creds_dict, f, indent=2)

def get_default_wallet():

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The helper returns Chinese-only labels, and those labels are injected into normal output regardless of user preference. This creates a locale/language policy issue because the skill forces a specific language without opt-in or documented regional scope.

Content

No source excerpt is available for this finding.

Tainted flow: 'slug' from requests.get (line 233, network input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · skill.py (reported line 245)May include surrounding context.

python
# Get odds
            try:
                d = requests.get(f"https://gamma-api.polymarket.com/events/slug/{slug}", timeout=5).json()
                markets = d.get('markets', [])
                opts = []
                for m in markets[:3]:

Tainted flow: 'slug' from requests.get (line 233, network input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · skill.py (reported line 273)May include surrounding context.

python
slug = slug.replace('event/', '').replace('https://polymarket.com/event/', '')
    
    try:
        resp = requests.get(f"https://gamma-api.polymarket.com/events/slug/{slug}", timeout=10)
        if resp.status_code != 200:
            print(f"❌ Not found: {resp.status_code}")
            return

Tainted flow: 'slug' from requests.get (line 233, network input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · skill.py (reported line 324)May include surrounding context.

python
slug = slug.replace('event/', '').replace('https://polymarket.com/event/', '')
    
    try:
        resp = requests.get(f"https://gamma-api.polymarket.com/events/slug/{slug}", timeout=10)
        if resp.status_code != 200:
            print(f"❌ Not found: {resp.status_code}")
            return

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill can place live market orders immediately on a buy/sell command with no confirmation prompt, preview, slippage warning, or dry-run safeguard. In an agent or automation setting, a mistaken command, prompt injection, or parameter mix-up could directly trigger irreversible financial transactions using the user's configured private key.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

Several printed labels in portfolio and balance views are in Chinese, and the file provides no mechanism for selecting language or opting into this locale. That constitutes a natural-language policy concern because the skill imposes a specific language on all users.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · skill.py (reported line 483)May include surrounding context.

python
def _balance_of(contract, decimals):
        data = f"0x70a08231000000000000000000000000{wallet[2:]}"
        try:
            resp = requests.post(POLYGON_RPC, json={"jsonrpc":"2.0","method":"eth_call","params":[{"to":contract,"data":data},"latest"],"id":1}, timeout=10)
            return int(resp.json().get("result", "0x0"), 16) / 10**decimals
        except:
            return None

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · skill.py (reported line 490)May include surrounding context.

python
def _balance_of(contract, decimals):
        data = f"0x70a08231000000000000000000000000{wallet[2:]}"
        try:
            resp = requests.post(POLYGON_RPC, json={"jsonrpc":"2.0","method":"eth_call","params":[{"to":contract,"data":data},"latest"],"id":1}, timeout=10)
            return int(resp.json().get("result", "0x0"), 16) / 10**decimals
        except:
            return None

Tainted flow: 'data' from requests.get (line 450, network input) → requests.post (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · skill.py (reported line 483)May include surrounding context.

python
def _balance_of(contract, decimals):
        data = f"0x70a08231000000000000000000000000{wallet[2:]}"
        try:
            resp = requests.post(POLYGON_RPC, json={"jsonrpc":"2.0","method":"eth_call","params":[{"to":contract,"data":data},"latest"],"id":1}, timeout=10)
            return int(resp.json().get("result", "0x0"), 16) / 10**decimals
        except:
            return None

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

The natural-language trigger section provides only Chinese and English examples, which can imply a language constraint in activation behavior. If the skill expects or prioritizes only those languages, that should be documented as an explicit choice rather than an unstated limitation.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

Examples like "这个市场什么意思", "What are the odds for [outcome]", and "Explain this market" do not clearly limit activation to Polymarket or prediction-market contexts. Without negative examples or stricter scoping, these phrases may collide with general requests about unrelated markets or events.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
90% confidence
Finding

The dependency specification uses a lower-bound only constraint (requests>=2.31.0) rather than pinning to a known-safe version, so the actual installed version may vary by environment and could resolve to a release affected by published advisories. In a trading skill that likely performs authenticated HTTP requests, an unsafe requests version could expose credentials or weaken transport/session security depending on runtime resolution.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency is specified with a lower bound only (requests>=2.31.0), which makes builds non-reproducible and allows future installs to resolve to unexpected versions. In a trading skill, dependency drift can introduce vulnerable or breaking releases into a network-facing component without code changes in the skill itself.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
# Polymarket Skill Dependencies
requests>=2.31.0
py-clob-client>=1.5.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
90% confidence
Finding

The manifest references requests without an exact version pin, and the package has multiple historical advisories, so the deployed environment could resolve to an affected release. While >=2.31.0 may avoid some older issues, the absence of a fixed reviewed version means exposure cannot be ruled out and is especially relevant for a CLI that makes authenticated HTTP requests.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
92% confidence
Finding

py-clob-client>=1.5.0 is also unpinned, so installations may pull different versions over time, including releases with undiscovered security issues or behavioral changes. Because this skill executes market actions, relying on floating versions in a trading client increases supply-chain and operational risk.

Content

Scanner excerpt · requirements.txt (reported line 3)May include surrounding context.

text
# Polymarket Skill Dependencies
requests>=2.31.0
py-clob-client>=1.5.0

Static analysis

No suspicious patterns detected.