T09 · Insecure Skill Coding Practices
- Location
discipline_scanner.py:23- Finding
Automated trading uses an unverified hardcoded wallet identity
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
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.
discipline_scanner.py:23Automated trading uses an unverified hardcoded wallet identity
discipline_scanner.py:76Automated take-profit scanner permits execution at 50% below the reported price
polyclaw_api.py:246Pre-trade risk check fails open with a fabricated balance
check_books.py:8Read-only order-book utility unnecessarily loads a private key and derives authenticated credentials
auto_redeem_check.py:108Auto-redemption grants persistent operator approval over all conditional tokens
pyproject.toml:7Security-sensitive dependencies are resolved from mutable version ranges without a lockfile
polyclaw_api.py:24Distributed artifact omits local modules required for documented security-sensitive operations
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.
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.
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.
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.
# 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
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.
cd {baseDir} && source .env && .venv/bin/python3 auto_redeem_check.py
*/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)
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.
# 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
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.
cd {baseDir} && export $(grep -v "^#" .env | xargs) && .venv/bin/python3 discipline_scanner.py
*/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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
#!/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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
#!/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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
#!/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
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# Ensure .env is loaded
from dotenv import load_dotenv
load_dotenv(Path(__file__).parent / ".env")
from portfolio_tracker import PortfolioTracker
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.
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.
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:
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.
Output size or generation rate is not bounded. Unbounded output enables denial-of-service through resource exhaustion, log flooding, or context-window stuffing.
**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
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.
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.
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.
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.
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.
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.
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.
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 calls execute external commands. Without careful input validation, this enables command injection.
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},
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.
No suspicious patterns detected.