Back to skill

Security audit

Polymarket Auto-Trader

Security checks for vulnerabilities and agentic risk

Overview

This skill is openly an autonomous real-money trading bot, but it gives broad persistent financial authority with weak runtime safeguards and includes jurisdiction-routing setup guidance.

Review this before installing as a high-risk real-money trading bot. Use only a dedicated low-balance wallet, revoke approvals when not needed, avoid running unattended cron until you add strict limits and monitoring, secure or replace plaintext private-key storage, and confirm you are legally and contractually allowed to use Polymarket from your location. I would not install it for live trading without adding dry-run mode, explicit confirmations, bounded allowances, market allowlists, and loss limits.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/run_trade.py:73
Finding

Untrusted market content influences autonomous live-trading decisions

Content
View full analysis
= 2 and len(tokens) >= 2: p0 = float(prices[0]) if p0 < 0.05 or p0 > 0.95: continue all_markets.append({ "question": m.get("question", ""), "description": m.get("description", "")[:400], "prices": [float(p) for p in prices], "tokens": tokens, "volume": float(m.get("volume", 0)), "end_date": m.get("endDate", "")[:10] }) except: continue def evaluate(market): prompt = f"""Estimate TRUE probability (0.0-1.0) YES wins. Be contrarian when justified. Q: {market['question']} Desc: {market['description'][:200]} YES price: {market['prices'][0]:.3f} End: {market['end_date']} Reply ONLY a number.""" resp = http_requests.post( "https://api.anthropic.com/v1/messages", headers={ "x-api-key": LLM_API_KEY, "anthropic-version": "2023-06-01", "Content-Type": "application/json" }, json={ "model": "claude-3-5-haiku-20241022", "max_tokens": 20, "messages": [{"role": "user", "content": prompt}] }, timeout=30 ) ``` The resulting estimate is then used to place live orders: ```python fair, cost = evaluate(m) total_eval_cost += cost if fair is None: continue mk ...[truncated 2475 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/approve_contracts.py:18
Finding

Unlimited USDC.e and unrestricted CTF operator approvals exceed least privilege

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:37
Finding

Wallet private key is stored in a plaintext environment file without enforced permissions

Content
View full analysis
LLM_API_KEY= ``` The VPS setup script repeats this instruction: ```bash echo "1. Create /opt/trader/app/.env with:" echo " PRIVATE_KEY=" echo " LLM_API_KEY=" ``` The trading script loads the plaintext file and obtains direct transaction-signing authority: ```python load_dotenv(WORKSPACE / ".env") PRIVATE_KEY = os.environ["PRIVATE_KEY"] LLM_API_KEY = os.environ["LLM_API_KEY"] ``` ### Technical Analysis The setup workflow requires a raw Polygon wallet private key to be stored on disk. The installation script creates `/opt/trader/app` but does not create the `.env` file with restrictive permissions, verify its owner, or reject execution when permissions are insecure. `SKILL.md:114` recommends `chmod 600 .env`, but this is advisory and is not incorporated into the actual setup or runtime checks. Depending on the user's umask and deployment process, the file may be readable by other local accounts, administrative services, backup tooling, or copied deployment artifacts. Because the same key is used to derive CLOB credentials and sign blockchain transactions, disclosure provides substantially more authority than disclosure of a limited API token. ### Attack Path 1. A user manually creates `/opt/trader/app/.env` under a permissive umask or through a deployment mechanism that preserves broad read permissions. 2. Another local user, compromised service, backup process, or artifact collector reads the file. 3. The attacker extracts `PRIVATE_KEY` and optionally `LLM_API_KEY`. 4. The attacker imports the wallet key on another system. 5. The attacker signs arbitrary Polygon transactions or der ...[truncated 690 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/setup_vps.sh:12
Finding

Python dependencies are installed without full lockfile and hash verification

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
Findings (24)

Tainted flow: 'LLM_API_KEY' from os.environ (line 22, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/run_trade.py (reported line 90)May include surrounding context.

python
def evaluate(market):
    prompt = f"Estimate TRUE probability (0.0-1.0) YES wins. Be contrarian when justified.\n\nQ: {market['question']}\nDesc: {market['description'][:200]}\nYES price: {market['prices'][0]:.3f}\nEnd: {market['end_date']}\n\nReply ONLY a number."
    resp = http_requests.post("https://api.anthropic.com/v1/messages", headers={"x-api-key": LLM_API_KEY, "anthropic-version": "2023-06-01", "Content-Type": "application/json"}, json={"model": "claude-3-5-haiku-20241022", "max_tokens": 20, "messages": [{"role": "user", "content": prompt}]}, timeout=30)
    data = resp.json()
    usage = data.get("usage", {})
    cost = budget.record(usage.get("input_tokens", 300), usage.get("output_tokens", 10))

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script submits live approval transactions that grant MAX_UINT ERC20 allowances and blanket ERC1155 operator approvals to multiple contracts immediately when run, with no interactive confirmation, dry-run mode, or explicit warning about the scope of access being granted. In the context of an autonomous trading skill, this is especially dangerous because unlimited approvals can persist indefinitely and allow a compromised, upgraded, or mistakenly configured spender contract to move all approved assets without further consent.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/pnl_tracker.py (reported line 11)May include surrounding context.

python
WORKSPACE = Path(__file__).resolve().parent
os.chdir(WORKSPACE)
from dotenv import load_dotenv
load_dotenv(WORKSPACE / ".env")

import requests as http_requests
from web3 import Web3

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/run_trade.py (reported line 10)May include surrounding context.

python
WORKSPACE = Path(__file__).resolve().parent
os.chdir(WORKSPACE)
from dotenv import load_dotenv
load_dotenv(WORKSPACE / ".env")

import requests as http_requests
from web3 import Web3

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script places live GTC orders directly against the Polymarket CLOB using a private key, based on unverified external market data and an LLM-generated probability estimate, without any human confirmation, dry-run default, circuit breaker, or explicit safety interlock. In this skill context, that is particularly dangerous because the stated purpose is autonomous trading with real funds, so a bad model output, API anomaly, or prompt/data manipulation can immediately cause irreversible financial loss.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The script instructs the user to create a .env containing a Polygon wallet private key, which is a highly sensitive credential that grants direct control over on-chain assets and trading actions. In this skill's context, compromise of that file could lead to immediate financial loss through unauthorized orders, transfers, or wallet drainage.

Content

Scanner excerpt · scripts/setup_vps.sh (reported line 23)May include surrounding context.

sh
echo "=== Setup complete ==="
echo ""
echo "Next steps:"
echo "1. Create /opt/trader/app/.env with:"
echo "   PRIVATE_KEY=<your-polygon-wallet-private-key>"
echo "   LLM_API_KEY=<your-anthropic-api-key>"
echo ""

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill requests and operationally depends on sensitive capabilities including environment-secret access, filesystem reads/writes, and network access, yet it does not declare an explicit tool/permission scope. That makes the agent's effective authority ambiguous and overly broad for a skill that stores a private key on disk and performs autonomous trading, increasing the chance of unintended secret exposure or unauthorized actions.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The description includes broad activation language like "Use when user wants to trade on Polymarket, set up automated prediction market trading, or build a trading bot," which can cause the skill to trigger on generic trading-related requests. In this context, overbroad activation is risky because the skill can lead to autonomous financial actions, secret handling, and persistent automation from loosely related prompts.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
93% confidence
Finding

The skill instructs users to install a cron job that repeatedly executes an autonomous trading script every 10 minutes, creating persistent behavior beyond the initiating session. Persistence is especially dangerous here because the job can continue spending funds, using API credits, and acting on stored private keys without renewed user review or runtime consent.

Content

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

5. Cron Automation

bash
crontab -e
# Add: */10 * * * * cd /opt/trader/app && /opt/trader/bin/python3 run_trade.py >> cron.log 2>&1

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 114)May include surrounding context.

md
## ⚠️ Security Considerations

- **Use a DEDICATED wallet with minimal funds.** Never use your main wallet's private key. Create a fresh wallet and fund it only with what you're willing to risk.
- **PRIVATE_KEY is stored on disk** in `.env`. Harden your VPS: strict file permissions (`chmod 600 .env`), no shared access, firewall, SSH keys only.
- **MAX_UINT approvals** are standard in DeFi but grant broad spending rights. The approved contracts are official Polymarket contracts. Review addresses in `references/contract-addresses.md` before running.
- **Test with tiny amounts first** ($5-10) before scaling up.
- **Monitor actively** — check `cron.log` and run `pnl_tracker.py` regularly.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The document explicitly instructs users to grant MAX_UINT256 approvals to multiple spender contracts, including three separate approvals for neg-risk markets, without any warning about the risks of unlimited allowances. If any approved contract is upgraded, compromised, misconfigured, or interacted with incorrectly, the approved spender could drain all approved USDC.e or transfer CTF positions without requiring fresh user consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The reference instructs users to instantiate the client with a raw wallet private key and derive API credentials from it, but provides no handling or storage safety guidance. In the context of an autonomous trading bot that can move real funds, normalizing direct private-key use increases the chance of credential leakage through logs, source files, environment mismanagement, or downstream agent misuse, which could lead to full account compromise and unauthorized trading.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The order placement example shows fully functional code to create and submit a live order without any warning that it executes real trades using user funds. Because this skill is specifically an autonomous trader, omission of a real-funds warning materially raises the risk of accidental execution, especially if a user or agent copies the snippet into production without safeguards, dry-run mode, or confirmation controls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script loads PRIVATE_KEY from the environment and immediately uses it to derive the account and sign live Polygon transactions, but it does not provide any explicit disclosure, confirmation, or safety barrier before using that credential. In an autonomous trading bot context, this increases risk because users may run setup scripts expecting configuration-only behavior, while the script actually performs privileged financial actions with a hot wallet key.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script reads a sensitive environment variable (PRIVATE_KEY) and immediately uses it to derive a wallet account and authenticate a ClobClient. Although this is central to the script's functionality, there is no confirmation prompt or user-facing disclosure that sensitive credentials will be accessed and used for external service authentication.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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 · scripts/run_trade.py (reported line 90)May include surrounding context.

python
def evaluate(market):
    prompt = f"Estimate TRUE probability (0.0-1.0) YES wins. Be contrarian when justified.\n\nQ: {market['question']}\nDesc: {market['description'][:200]}\nYES price: {market['prices'][0]:.3f}\nEnd: {market['end_date']}\n\nReply ONLY a number."
    resp = http_requests.post("https://api.anthropic.com/v1/messages", headers={"x-api-key": LLM_API_KEY, "anthropic-version": "2023-06-01", "Content-Type": "application/json"}, json={"model": "claude-3-5-haiku-20241022", "max_tokens": 20, "messages": [{"role": "user", "content": prompt}]}, timeout=30)
    data = resp.json()
    usage = data.get("usage", {})
    cost = budget.record(usage.get("input_tokens", 300), usage.get("output_tokens", 10))

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 · scripts/run_trade.py (reported line 90)May include surrounding context.

python
def evaluate(market):
    prompt = f"Estimate TRUE probability (0.0-1.0) YES wins. Be contrarian when justified.\n\nQ: {market['question']}\nDesc: {market['description'][:200]}\nYES price: {market['prices'][0]:.3f}\nEnd: {market['end_date']}\n\nReply ONLY a number."
    resp = http_requests.post("https://api.anthropic.com/v1/messages", headers={"x-api-key": LLM_API_KEY, "anthropic-version": "2023-06-01", "Content-Type": "application/json"}, json={"model": "claude-3-5-haiku-20241022", "max_tokens": 20, "messages": [{"role": "user", "content": prompt}]}, timeout=30)
    data = resp.json()
    usage = data.get("usage", {})
    cost = budget.record(usage.get("input_tokens", 300), usage.get("output_tokens", 10))

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 · scripts/run_trade.py (reported line 90)May include surrounding context.

python
def evaluate(market):
    prompt = f"Estimate TRUE probability (0.0-1.0) YES wins. Be contrarian when justified.\n\nQ: {market['question']}\nDesc: {market['description'][:200]}\nYES price: {market['prices'][0]:.3f}\nEnd: {market['end_date']}\n\nReply ONLY a number."
    resp = http_requests.post("https://api.anthropic.com/v1/messages", headers={"x-api-key": LLM_API_KEY, "anthropic-version": "2023-06-01", "Content-Type": "application/json"}, json={"model": "claude-3-5-haiku-20241022", "max_tokens": 20, "messages": [{"role": "user", "content": prompt}]}, timeout=30)
    data = resp.json()
    usage = data.get("usage", {})
    cost = budget.record(usage.get("input_tokens", 300), usage.get("output_tokens", 10))

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script explicitly instructs deployment on a 'non-US VPS', which is geolocation-based operational guidance unrelated to basic software setup and strongly suggests an attempt to route activity through a specific jurisdiction. In the context of an autonomous trading bot for a regulated prediction market, this increases the risk of policy, compliance, or access-control evasion and makes the deployment materially more dangerous than a generic hosting recommendation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Directing users to run the system on a 'non-US VPS' imposes a geographic constraint without technical justification and appears designed to influence how the service is accessed rather than how it functions. In a trading-agent context, that can facilitate circumvention of market/platform regional restrictions, making the instruction security- and compliance-relevant rather than a harmless comment.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The setup instructions tell the user to place a blockchain private key and API key into a .env file without any accompanying safeguards, such as file permissions, exclusion from version control, or use of a secrets manager. Because the bot executes trades and holds wallet credentials, exposure of these secrets could directly enable unauthorized trading or theft of funds.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/setup_vps.sh (reported line 33)May include surrounding context.

sh
echo "3. Copy trading scripts to /opt/trader/app/"
echo ""
echo "4. Set up cron:"
echo "   crontab -e"
echo "   */10 * * * * cd /opt/trader/app && /opt/trader/bin/python3 run_trade.py >> cron.log 2>&1"

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The cancellation example performs a destructive account action but does not warn that it may cancel active orders and disrupt trading strategy or execution. In an autonomous bot context, undocumented destructive actions can cause financial loss through missed fills, strategy interference, or unintended mass cancellation if the pattern is generalized by the agent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The script sends market questions and portfolio-related lookups to remote services via HTTP requests to Polymarket endpoints. While these calls support the script's purpose, there is no explicit user-facing warning that local trade-derived market identifiers and account-linked queries will be sent to third-party services.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.