Back to skill

Security audit

PolyClaw Pro

Security checks for vulnerabilities and agentic risk

Overview

This Polymarket trading skill is not clearly malicious, but it can use wallet keys for unattended trades and redemptions and contains hardcoded, incomplete account-handling code that needs careful review.

Review this skill before installing. Use only a low-balance throwaway wallet, do not enable the cron jobs or API swap bridge until the hardcoded wallet addresses are removed, all missing modules are supplied and audited, dependencies are pinned, and every transaction path has explicit account checks, limits, and manual approval for first-time or high-impact actions.

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

T09 · Insecure Skill Coding Practices

Error
Location
discipline_scanner.py:23
Finding
Automated trading uses an unverified hardcoded wallet identity<![CDATA[ ## Vulnerability Details **File Location**: `discipline_scanner.py:23-29, 60-65, 100-103` **Vulnerability Type**: Wallet and signer identity mismatch **Risk Level**: High ### Vulnerable Code ```python wallet = "0x2aacf919270Ae303fD3FE8e27D96CBA250936B9F" ctx = ssl.create_default_context() req = urllib.request.Request( f"https://data-api.polymarket.com/positions?user={wallet}&sizeThreshold=0", headers={"User-Agent": "Mozilla/5.0"} ) with urllib.request.urlopen(req, timeout=15, context=ctx) as r: positions = json.loads(r.read()) ``` ```python from trade_tor import patch_httpx_for_tor, get_client import httpx from py_clob_client.clob_types import OrderArgs, OrderType from py_clob_client.order_builder.constants import SELL as SELL_SIDE patch_httpx_for_tor() client = get_client() ``` ```python order = client.create_order( OrderArgs(token_id=token_id, price=best_bid, size=sell_size, side=SELL_SIDE) ) result = client.post_order(order, OrderType.FOK) ``` ### Technical Analysis The scanner obtains positions for a fixed wallet, but the authenticated trading client is created independently by `trade_tor.get_client()`. The code does not verify that the client's signer and funder correspond to the wallet used to select positions. This violates a critical invariant for automated trading: the position owner, signing account, and funding account must be the same expected identity. If the configured private key belongs to another wallet, the scanner can select token IDs and quantities using unrelated account data before attempting authenticated sell orders. The referenced `trade_tor` module is absent from the supplied artifact, so this path cannot execute as packaged. Nevertheless, the identity-validation defect is explicit in the available scanner and would become reachable when the missing module is supplied. ### Attack Path 1. The operator configures a private key whose address differs from the hardcoded wallet. 2. The cron task queries p ...[truncated 812 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Derive the queried wallet address directly from the configured private key. - Require `queried_wallet == signer_address == funder_address` before loading positions or creating orders. - Remove the hardcoded wallet address. - Abort rather than trade when any identity cannot be verified. - Add chain-ID and CLOB-host validation. - Add tests that configure mismatched wallets and confirm that no order can be created or posted. - Package and audit the referenced `trade_tor` module before enabling the scanner. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
discipline_scanner.py:76
Finding
Automated take-profit scanner permits execution at 50% below the reported price<![CDATA[ ## Vulnerability Details **File Location**: `discipline_scanner.py:76-103` **Vulnerability Type**: Unsafe automated trade execution and inadequate slippage control **Risk Level**: High ### Vulnerable Code ```python try: ob = client.get_order_book(token_id) bids = ob.bids if ob.bids else [] best_bid = float(bids[0].price) if bids else 0 except: best_bid = 0 # Guard: don't sell if best_bid < 50% of our expected price min_acceptable = t["cur"] * 0.50 if best_bid < min_acceptable: print(f" SKIP {t['title']}: bid=${best_bid:.3f} too low vs cur=${t['cur']:.3f} (min ${min_acceptable:.3f})") print(f" This position should wait for settlement or better liquidity") continue # Guard: don't sell if absolute bid < $0.05 (dust orders) if best_bid < 0.05: print(f" SKIP {t['title']}: bid=${best_bid:.3f} is dust, wait for settlement") continue expected_return = sell_size * best_bid print(f" SELL {t['title']} | {sell_size} @ bid=${best_bid:.3f} | ~${expected_return:.2f} | ({t['pnl_pct']:+.0%})") try: order = client.create_order( OrderArgs(token_id=token_id, price=best_bid, size=sell_size, side=SELL_SIDE) ) result = client.post_order(order, OrderType.FOK) ``` ### Technical Analysis The mechanism is described as slippage protection, but it allows a full-position sale when the best bid is as low as half the API-reported current price. The code also checks only the first bid and does not verify that sufficient depth exists to satisfy the intended size at an acceptable effective price. The scanner runs unattended through a documented cron configuration. Consequently, stale Data API prices, temporary illiquidity, malformed order-book ordering, or abnormal spreads can automatically trigger materially unfavorable trades. ### Attack Path 1. A position exceeds the configured take-profit threshold according to the Data API price. 2. The market becomes illiquid or the displayed best bid falls to slightly more t ...[truncated 528 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Replace the 50% threshold with a conservative, configurable maximum slippage value. - Calculate executable depth and volume-weighted price for the full order size. - Reject stale quotes and require timestamps within a short tolerance. - Limit the maximum quantity and notional value sold in one unattended run. - Require manual confirmation when the spread or price deviation exceeds a narrow threshold. - Validate order-book sorting rather than assuming the first element is the best bid. - Record the reference price, bid depth, and final fill price in an immutable audit log. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
polyclaw_api.py:246
Finding
Pre-trade risk check fails open with a fabricated balance<![CDATA[ ## Vulnerability Details **File Location**: `polyclaw_api.py:246-263` **Vulnerability Type**: Fail-open financial risk control **Risk Level**: High ### Vulnerable Code ```python def cmd_risk_check(amount_str, slug, channel): """Pre-trade risk check.""" pt = PortfolioTracker() amount = float(amount_str) # Get CLOB balance for reserve check try: from py_clob_client.client import ClobClient pk = os.environ.get("POLYCLAW_PRIVATE_KEY", "") wallet_addr = "0x2aacf919270Ae303fD3FE8e27D96CBA250936B9F" clob = ClobClient("https://clob.polymarket.com", key=pk, chain_id=137, signature_type=0, funder=wallet_addr) creds = clob.create_or_derive_api_creds() clob.set_api_creds(creds) bal = clob.get_balance_allowance() clob_balance = float(bal.get("balance", 0)) / 1e6 except Exception: clob_balance = 999 # Fallback: don't block on balance check failure ok, reason = pt.check_risk(amount, slug, channel, clob_balance) print(json.dumps({"ok": ok, "reason": reason, "clob_balance": round(clob_balance, 2)})) ``` ### Technical Analysis Any exception during import, key handling, credential derivation, authentication, network communication, response parsing, or balance conversion is converted into a fictitious balance of `$999`. A risk control must fail closed when authoritative financial state cannot be established. This implementation instead treats an unknown balance as sufficient funds, allowing downstream logic to approve a trade based on invented data. ### Attack Path 1. The CLOB balance request fails because of a network outage, invalid credential, malformed response, blocked endpoint, or dependency failure. 2. The broad exception handler suppresses the cause. 3. `clob_balance` is set to `999`. 4. `PortfolioTracker.check_risk()` receives the fabricated value. 5. A trade that should be rejected for insufficient or unverifiable funds may ...[truncated 244 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Fail closed when the balance cannot be verified. - Return a structured error such as `{"ok": false, "reason": "balance unavailable"}`. - Catch specific exceptions and log their causes without exposing secrets. - Never substitute a nonzero financial value for unavailable authoritative state. - Add retry logic with bounded exponential backoff where appropriate. - Verify that the wallet derived from the private key matches the configured funder before requesting balances. - Add tests covering network, authentication, parsing, and empty-key failures. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
check_books.py:8
Finding
Read-only order-book utility unnecessarily loads a private key and derives authenticated credentials<![CDATA[ ## Vulnerability Details **File Location**: `check_books.py:8-25` **Vulnerability Type**: Excessive credential privilege for public market-data access **Risk Level**: Medium ### Vulnerable Code ```python CLOB_HOST = "https://clob.polymarket.com" GAMMA_API = "https://gamma-api.polymarket.com" TOR_PROXY = "socks5://127.0.0.1:9050" PK = os.environ.get("POLYCLAW_PRIVATE_KEY", "") WALLET = "0x2aacf919270Ae303fD3FE8e27D96CBA250936B9F" def patch(): clob_helpers._http_client = httpx.Client(proxy=TOR_PROXY, timeout=30.0, follow_redirects=True) patch() def get_client(): c = ClobClient(CLOB_HOST, key=PK, chain_id=137, signature_type=0, funder=WALLET) creds = c.create_or_derive_api_creds() c.set_api_creds(creds) return c client = get_client() ``` ### Technical Analysis The script's stated purpose is to inspect order books. Nevertheless, it reads the wallet's private key, creates an authenticated CLOB client, and derives API credentials. Public order-book inspection does not require wallet signing authority. This exceeds least privilege and unnecessarily exposes sensitive key material to the Python process, CLOB client implementation, transitive dependencies, and any monkey-patched HTTP stack. The configured funder is also a hardcoded wallet rather than an address validated against the key. ### Attack Path 1. An operator runs the diagnostic while the private key is present in the environment. 2. The script loads the key even though no authenticated operation is required. 3. `create_or_derive_api_creds()` performs signing-related credential derivation. 4. Any compromised dependency, debugging hook, or modified client code executing in the process can access the credential context. 5. The unnecessary exposure can facilitate unauthorized authenticated CLOB activity. ### Impact Assessment The direct script only reads order books, but it unnecessarily places trading-capable wallet credentials into a larger execution context. The potential ...[truncated 87 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Use the unauthenticated public CLOB order-book client or REST endpoint. - Remove all references to `POLYCLAW_PRIVATE_KEY`, funder addresses, and credential derivation from this script. - Separate public market-data clients from authenticated trading clients. - Ensure diagnostic utilities can run in an environment where no wallet secret is present. - If authentication becomes necessary in the future, use narrowly scoped API credentials rather than the wallet private key. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
auto_redeem_check.py:108
Finding
Auto-redemption grants persistent operator approval over all conditional tokens<![CDATA[ ## Vulnerability Details **File Location**: `auto_redeem_check.py:108-124` **Vulnerability Type**: Overbroad and persistent token-operator approval **Risk Level**: Medium ### Vulnerable Code ```python if is_neg: # Ensure approval approved = ctf.functions.isApprovedForAll( Web3.to_checksum_address(WALLET), NEG_RISK ).call() if not approved: print(" Approving NegRiskAdapter...") tx = ctf.functions.setApprovalForAll(NEG_RISK, True).build_transaction({ "from": Web3.to_checksum_address(WALLET), "nonce": nonce, "gas": 60000, "gasPrice": int(w3.eth.gas_price * 1.2), }) signed = w3.eth.account.sign_transaction(tx, PK) tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction) w3.eth.wait_for_transaction_receipt(tx_hash, timeout=60) nonce += 1 ``` ### Technical Analysis `setApprovalForAll` authorizes the NegRiskAdapter as an operator for all conditional tokens owned by the wallet, including future tokens. The approval is not restricted to the position being redeemed and is never revoked. The adapter is a declared Polymarket contract, so the approval supports legitimate redemption behavior. However, the permission exceeds the minimum scope of one redemption and remains active after the cron invocation. The script also relies only on a hardcoded address and does not verify the chain ID or deployed bytecode before granting authority. ### Attack Path 1. The cron scanner finds a resolved negative-risk position. 2. It observes that the adapter is not currently approved. 3. It signs and broadcasts `setApprovalForAll(adapter, true)`. 4. The redemption completes or fails, but the global approval remains active. 5. If the wrong chain, wrong deployment, compromised adapter, or configuration error is involved, the approved operator may act on all current and future conditional tokens. ### Impact Assessment The approval affects all conditional tokens held b ...[truncated 136 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Verify `w3.eth.chain_id == 137` before signing any transaction. - Verify the expected deployed bytecode or code hash at the adapter and CTF addresses. - Clearly disclose that `setApprovalForAll` is a durable wallet-wide authorization. - Prefer a position-scoped authorization mechanism if supported. - If operationally feasible, revoke the approval after redemption. - Provide a command that reports and revokes outstanding approvals. - Require explicit opt-in before the first global approval instead of creating it silently during an unattended cron run. ]]>

T08 · Insecure Dependencies

Warning
Location
pyproject.toml:7
Finding
Security-sensitive dependencies are resolved from mutable version ranges without a lockfile<![CDATA[ ## Vulnerability Details **File Location**: `pyproject.toml:7-14` **Vulnerability Type**: Unlocked security-sensitive dependency resolution **Risk Level**: Medium ### Vulnerable Code ```toml dependencies = [ "web3>=7.0.0", "httpx[socks]>=0.28.0", "py-clob-client>=0.34.0", "eth-account>=0.13.0", "python-dotenv>=1.0.0", "curl-cffi>=0.14.0", ] ``` ### Technical Analysis All dependencies use open-ended lower bounds, and the audited artifact contains no lockfile. Future installations can therefore resolve newer versions that were not reviewed with this code. This is especially significant because `web3`, `eth-account`, and `py-clob-client` run in processes that load private keys, derive credentials, sign transactions, and submit orders. No malicious package name or nonstandard package source was observed; the issue is mutable and unreproducible resolution rather than confirmed dependency confusion. ### Attack Path 1. A new dependency or transitive dependency release becomes available. 2. A user follows the documented `uv sync` installation procedure. 3. The resolver selects the new, unreviewed release because no upper bound or committed lockfile constrains it. 4. The package executes in a process containing wallet secrets and signing authority. 5. A compromised or behaviorally incompatible release could expose credentials or alter transaction behavior. ### Impact Assessment The possible scope includes the environment variables, wallet private key, CLOB credentials, RPC traffic, signed transactions, and trading operations available to the application process. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Generate and commit a reviewed `uv.lock`. - Pin direct security-critical dependencies to tested versions. - Use automated vulnerability scanning and controlled dependency-update reviews. - Review transitive dependencies that process wallet secrets or network traffic. - Rebuild from the lockfile in deployment and verify package hashes. - Avoid exposing private keys to processes with unnecessary dependencies. ]]>

other

Warning
Location
polyclaw_api.py:24
Finding
Distributed artifact omits local modules required for documented security-sensitive operations<![CDATA[ ## Vulnerability Details **File Location**: `polyclaw_api.py:24-25, 273-279`; related import at `discipline_scanner.py:60` **Vulnerability Type**: Incomplete and unverifiable packaged implementation **Risk Level**: Medium ### Vulnerable Code ```python from portfolio_tracker import PortfolioTracker ``` ```python def cmd_swap(action): """Delegate to swap.py.""" import subprocess result = subprocess.run( [sys.executable, str(Path(__file__).parent / "swap.py"), action], capture_output=True, text=True, timeout=120, env={**os.environ}, ) ``` Related scanner import: ```python from trade_tor import patch_httpx_for_tor, get_client ``` ### Technical Analysis The supplied project does not contain `portfolio_tracker.py`, `swap.py`, or `trade_tor.py`. The README also documents `scripts/` and `lib/` trees that are absent from the artifact. These missing components are expected to implement portfolio state management, authenticated client creation, trading, and token swaps. Their absence prevents the advertised workflows from running as supplied and prevents review of critical credential and transaction-handling paths. This is not evidence that the missing code is malicious. It is a packaging and auditability defect that becomes security-relevant because users are instructed to provide a private key before invoking workflows whose effective implementation is incomplete. ### Attack Path 1. A user follows the documentation and configures `POLYCLAW_PRIVATE_KEY` and RPC credentials. 2. The user invokes the API bridge, swap command, or discipline scanner. 3. Execution attempts to import or run a missing component. 4. The operation fails, or the user obtains the missing component from an unaudited external source to restore functionality. 5. Any substituted implementation then receives the inherited environment, including wallet secrets and transaction authority. ### Impact Assessment As packaged, the primary impact is f ...[truncated 252 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Include every referenced local module in the distributed artifact. - Make the documented directory structure match the actual package. - Add startup integrity checks that enumerate required local files before loading wallet credentials. - Do not request or load private keys until package completeness has been verified. - Add installation tests covering every documented command. - Publish cryptographic hashes or signed releases for all security-sensitive local modules. - Remove commands and documentation for components that are not distributed. ]]>
Vulnerability Patterns
  • 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
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (33)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
A substantial description-behavior mismatch is security-relevant because users may grant wallet, network, and secret access under false assumptions about what the skill actually does. In this context, undeclared proxy usage, private-key-derived API auth, or hidden wallet-specific behavior would materially change the trust boundary for a financial automation skill.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
A substantial description-behavior mismatch is security-relevant because users may grant wallet, network, and secret access under false assumptions about what the skill actually does. In this context, undeclared proxy usage, private-key-derived API auth, or hidden wallet-specific behavior would materially change the trust boundary for a financial automation skill.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
A substantial description-behavior mismatch is security-relevant because users may grant wallet, network, and secret access under false assumptions about what the skill actually does. In this context, undeclared proxy usage, private-key-derived API auth, or hidden wallet-specific behavior would materially change the trust boundary for a financial automation skill.

Credential Access

High
Category
Privilege Escalation
Content
```bash
# Manual run
cd {baseDir} && source .env && .venv/bin/python3 auto_redeem_check.py

# Cron (every 15 minutes)
*/15 * * * * cd /path/to/polyclaw && source .env && .venv/bin/python3 auto_redeem_check.py >> /var/log/polyclaw-redeem.log 2>&1
Confidence
80% confidence
Finding
The documented pattern of sourcing a .env file before running a transaction-capable script exposes sensitive credentials into the process environment and normalizes secret handling through shell commands. In a wallet-enabled trading skill, this increases the blast radius of accidental disclosure via subprocesses, shell history, debugging output, misconfigured permissions, or multi-user systems.

Credential Access

High
Category
Privilege Escalation
Content
cd {baseDir} && source .env && .venv/bin/python3 auto_redeem_check.py

# Cron (every 15 minutes)
*/15 * * * * cd /path/to/polyclaw && source .env && .venv/bin/python3 auto_redeem_check.py >> /var/log/polyclaw-redeem.log 2>&1
```

- Requires `web3` (use `.venv/bin/python3`, not system python)
Confidence
80% confidence
Finding
Embedding cron examples that source .env for an automated redeem script encourages persistent unattended use of wallet secrets in an environment-exposed form. Because the script can redeem on-chain positions, compromise of that runtime or its logs/process metadata could lead to unauthorized fund movements or operational abuse.

Credential Access

High
Category
Privilege Escalation
Content
```bash
# Manual run
cd {baseDir} && export $(grep -v "^#" .env | xargs) && .venv/bin/python3 discipline_scanner.py

# Cron (every 30 minutes)
*/30 * * * * cd /path/to/polyclaw && export $(grep -v "^#" .env | xargs) && .venv/bin/python3 discipline_scanner.py >> /var/log/polyclaw-discipline.log 2>&1
Confidence
87% confidence
Finding
Using `export $(grep -v "^#" .env | xargs)` is particularly risky because it performs brittle shell parsing of secrets and exports them broadly to the process environment. In a financial automation context, this can mis-handle special characters, leak credentials to child processes, and create avoidable exposure for the private key used to sell positions automatically.

Credential Access

High
Category
Privilege Escalation
Content
cd {baseDir} && export $(grep -v "^#" .env | xargs) && .venv/bin/python3 discipline_scanner.py

# Cron (every 30 minutes)
*/30 * * * * cd /path/to/polyclaw && export $(grep -v "^#" .env | xargs) && .venv/bin/python3 discipline_scanner.py >> /var/log/polyclaw-discipline.log 2>&1
```

- Skips positions worth less than $1
Confidence
87% confidence
Finding
The cron-based discipline scanner combines automated trade execution with environment-exported secrets, creating a high-risk unattended pathway for asset sales. If the host, job definition, or environment handling is compromised, an attacker may gain access to the private key or influence automated sell behavior.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""Auto-redeem checker: runs via cron, checks if winning positions have resolved on-chain.
When payoutDenominator > 0, immediately redeem via NegRiskAdapter.
Add to crontab: */15 * * * * cd /root/.openclaw/skills/polyclaw && source .env && .venv/bin/python3 auto_redeem_check.py >> /var/log/polyclaw-redeem.log 2>&1
"""
import os, json, urllib.request, ssl, time
from datetime import datetime, timezone
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""Auto-redeem checker: runs via cron, checks if winning positions have resolved on-chain.
When payoutDenominator > 0, immediately redeem via NegRiskAdapter.
Add to crontab: */15 * * * * cd /root/.openclaw/skills/polyclaw && source .env && .venv/bin/python3 auto_redeem_check.py >> /var/log/polyclaw-redeem.log 2>&1
"""
import os, json, urllib.request, ssl, time
from datetime import datetime, timezone
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""Auto-redeem checker: runs via cron, checks if winning positions have resolved on-chain.
When payoutDenominator > 0, immediately redeem via NegRiskAdapter.
Add to crontab: */15 * * * * cd /root/.openclaw/skills/polyclaw && source .env && .venv/bin/python3 auto_redeem_check.py >> /var/log/polyclaw-redeem.log 2>&1
"""
import os, json, urllib.request, ssl, time
from datetime import datetime, timezone
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Ensure .env is loaded
from dotenv import load_dotenv
load_dotenv(Path(__file__).parent / ".env")

from portfolio_tracker import PortfolioTracker
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Missing User Warnings

High
Confidence
94% confidence
Finding
This API bridge exposes a `swap auto` pathway that delegates directly to a local trading helper and can trigger irreversible asset conversions. In the skill context, this bridge is designed for remote bot invocation over SSH, so exposing a high-impact trading action without confirmation, allowlisting, or clear guardrails materially increases the chance of accidental or unauthorized asset movement.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
result = subprocess.run(
        [sys.executable, str(Path(__file__).parent / "swap.py"), action],
        capture_output=True, text=True, timeout=120,
        env={**os.environ},
    )
    print(result.stdout)
    if result.stderr:
Confidence
90% confidence
Finding
Passing the full parent environment to a subprocess (`env={**os.environ}`) unnecessarily propagates all loaded secrets, including Web3 credentials from `.env`, into `swap.py`. In this skill, the bridge explicitly loads secrets and performs financial operations, so broad environment inheritance expands the blast radius if the helper script, its dependencies, logging, or error handling are compromised.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill requests or implies powerful capabilities (environment access, file read/write, network, shell) but does not declare an explicit tool scope or permission boundary. In a trading skill that handles private keys and can submit transactions, this increases the risk of overbroad execution and makes review, sandboxing, and user consent materially weaker.

Unbounded Output

Medium
Category
Output Handling
Content
**Output options:**
- Default output is a formatted table (good for display)
- Use `--full` flag for full question text without truncation
- Use `--json` flag via `scripts/markets.py --json trending` for structured JSON output

### Wallet Management
Confidence
60% confidence
Finding
Output size or generation rate is not bounded. Unbounded output enables denial-of-service through resource exhaustion, log flooding, or context-window stuffing.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The automation sections describe unattended execution paths that can redeem positions or sell profitable holdings on a cron schedule, but the warning about autonomous financial actions is not prominent relative to the instructions. In a live trading skill using a private key from environment variables, this can cause unintended fund movement or liquidation if misconfigured, triggered in the wrong environment, or used by an inattentive operator.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
This script automatically signs and broadcasts on-chain transactions using a hot private key loaded from the environment, then is explicitly intended to run unattended via cron. In the context of a trading/portfolio automation skill, that creates real risk of irreversible asset movement, accidental approvals, and damage from misconfiguration or compromise of the host, environment, or upstream data sources without any human review at execution time.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
This script is presented as an order-book checker, but it initializes a trading client with a private key and derives API credentials even though the visible functionality only reads public market and order-book data. Loading signing material unnecessarily expands the blast radius: anyone running the script exposes sensitive credentials to imported code paths, memory, logs, exceptions, or future modifications without any operational need for read-only book inspection.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The code silently reads a private key from an environment variable and immediately uses it to derive API credentials, with no disclosure to the user that running a seemingly read-only utility will access wallet secrets. In the context of a trading skill that also includes automation and API bridging, this is more dangerous because users may execute helper scripts assuming low risk while unintentionally exposing high-value credentials needed for account actions.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The script is mislabeled as checking current positions, but it never authenticates to a wallet, exchange, or portfolio source and only fetches public market data based on hardcoded queries and trending lists. In a trading/automation skill, this can mislead users or downstream agents into believing the output reflects actual holdings, which may drive incorrect trading, hedging, or risk-management decisions.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The code sends the wallet address in outbound requests to the Polymarket Data API, which transmits user/system-linked financial metadata over the network. While the code includes technical docstrings, it does not provide a clear user-facing warning that wallet information will be shared with external services.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The code reads the POLYCLAW_PRIVATE_KEY environment variable and derives the wallet address from it, which is sensitive credential handling. Although the function has a docstring about balances, there is no explicit warning, confirmation, or user-facing disclosure that private-key-backed credentials are being accessed.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The manifest describes a Polymarket trading and portfolio skill, and while token swapping may fit that domain, this file's API bridge implements that feature by spawning a separate Python process. Subprocess execution is a broader capability than the stated bridge/portfolio interface and is not justified by the manifest text for this interface layer itself.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def cmd_swap(action):
    """Delegate to swap.py."""
    import subprocess
    result = subprocess.run(
        [sys.executable, str(Path(__file__).parent / "swap.py"), action],
        capture_output=True, text=True, timeout=120,
        env={**os.environ},
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Vague Triggers

Medium
Confidence
88% confidence
Finding
This manifest file describes the skill only as a "Trading-enabled Polymarket skill for OpenClaw" without specifying any concrete invocation phrases, scope limits, or exclusion conditions. In a manifest, such broad natural-language descriptions can contribute to ambiguous matching and unintended activation because the trigger context is not clearly bounded.

Static analysis

No suspicious patterns detected.