Back to skill

Security audit

Cross Funding Arb

Security checks for vulnerabilities and agentic risk

Overview

This is a real automated crypto trading skill, but it uses high-impact credentials and scheduled execution with several under-scoped safety issues users should review carefully.

Install only if you are comfortable running an automated live futures trader. Use least-privilege exchange credentials with withdrawals disabled, prefer testnet or small explicit budgets first, do not rely on the documented 50% budget limit until the implementation is fixed, avoid sourcing `.env` in shell or cron, and provide dedicated notification bot tokens instead of letting the skill reuse OpenClaw or ZeroClaw daemon credentials.

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

T05 · Unauthorized Access and Privilege Escalation

Error
Location
references/cross_funding.py:192
Finding

Overbroad Access to OpenClaw and ZeroClaw Credential Stores

Content
View full analysis
list[dict]: """Read all available daemon configs for bot token resolution. Returns a list of config sources (OpenClaw JSON + ZeroClaw TOML instances). Callers try each source in order until a token is found. """ sources: list[dict] = [] # OpenClaw: JSON format oc_path = Path.home() / ".openclaw" / "openclaw.json" if oc_path.exists(): try: data = json.loads(oc_path.read_text()) channels = data.get("channels", {}) sources.append({"_type": "openclaw", "_data": channels}) except Exception: pass # ZeroClaw: TOML format (try all instances) for instance in ["zeroclaw-strategy", "zeroclaw", "zeroclaw-data", "zeroclaw-ops"]: cfg_path = Path.home() / f".{instance}" / "config.toml" if cfg_path.exists(): try: sources.append({"_type": "zeroclaw", "_text": cfg_path.read_text()}) except Exception: pass return sources _DAEMON_CONFIGS = _read_daemon_configs() def _get_discord_token() -> str: """Discord bot token: env > first available daemon config.""" env_token = os.environ.get("DISCORD_BOT_TOKEN", "") if env_token: return env_token for cfg in _DAEMON_CONFIGS: token = "" if cfg["_type"] == "openclaw": token = cfg.get("_data", {}).get("discord", {}).get("token", "") elif cfg["_type"] == "zeroclaw": section = _parse_toml_section( cfg.get("_text", ""), "channels_config.discord" ) token = section.get("bot_token", "") if token: return token return "" def _get_telegram_config() -> tuple[str, str]: """Telegram creds: ...[truncated 3191 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
references/cross_funding.py:1295
Finding

Position-Closing Orders Do Not Enforce Reduce-Only Semantics

Content
View full analysis
dict | None: pos = self.get_position(coin) if not pos or pos["size"] == 0: return None is_buy = pos["size"] < 0 size = abs(pos["size"]) return self.market_order(coin, is_buy, size, slippage=slippage) ``` Binance closing path: ```python def close_position(self, coin: str, *, slippage: float = 0.001) -> dict | None: pos = self.get_position(coin) if not pos or pos["size"] == 0: return None is_buy = pos["size"] < 0 size = abs(pos["size"]) return self.market_order(coin, is_buy, size, slippage=slippage) ``` The Binance order parameters also omit `reduceOnly`: ```python params = { "symbol": symbol, "side": "BUY" if is_buy else "SELL", "type": "LIMIT", "quantity": size, "price": px, "timeInForce": "IOC", } ``` ### Technical Analysis Both closing methods first read a position and then submit a normal order for the observed position size. Neither order is constrained to reduce an existing position. This creates a time-of-check/time-of-use race. The position can change after `get_position()` due to partial liquidation, manual trading, another strategy, exchange-side adjustments, or a previous order completing asynchronously. If the close order exceeds the remaining position, it can cross through zero and create a new position in the opposite direction. This is particularly dangerous in a cross-exchange strategy because a reversed position can turn a nominally delta-neutral pair into two legs exposed in the same direction. ### Attack Path 1. The engine reads an existing position and calculates its closing side and size. 2. Before the close order reaches the exchange, the positio ...[truncated 1055 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
references/cross_funding.py:2124
Finding

Runtime Capital Allocation Exceeds the Documented Safety Limit

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
README.md:49
Finding

Scheduled Tasks Execute the Credential File as Shell Code

Content
View full analysis
> /tmp/cross_funding.log 2>&1 ``` Equivalent scheduled commands appear at `SKILL.md:362-390`: ```bash openclaw cron add \ --name "cross-funding-tick" \ --cron "*/5 * * * *" \ --session main \ --system-event "cd $SKILL_DIR && set -a && . ./.env && set +a && python3 cross_funding.py tick" ``` ```bash zeroclaw cron add --expr "*/5 * * * *" --shell \ "cd $SKILL_DIR && set -a && . ./.env && set +a && python3 cross_funding.py tick" ``` The Python entry point already parses `.env` at `references/cross_funding.py:3956`: ```python load_dotenv(script_dir / ".env") ``` ### Technical Analysis The documentation instructs users to source `.env` through a shell: ```bash . ./.env ``` Shell sourcing does not treat the file as inert key-value data. It executes all valid shell syntax contained in the file. Because this command is installed as a recurring task, modification of `.env` becomes a persistent arbitrary-command execution path under the account that owns the scheduled task. The shell execution is unnecessary because the program already calls `load_dotenv()` and can parse the file without interpreting shell commands. The scheduled task itself is consistent with the declared need for continuous market monitoring and is not hidden. The vulnerability is the unsafe recurring execution of a credential file as code. ### Attack Path 1. The operator follows the deployment documentation and registers the five-minute scheduled task. 2. An attac ...[truncated 1255 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
references/requirements.txt:1
Finding

Security-Critical Dependencies Are Installed Without Exact Version or Integrity Pinning

Content
View full analysis
=0.21.0 eth-account>=0.13.7 python-dotenv>=1.0.0 requests>=2.31.0 ``` The installation instructions at `README.md:19-20` execute these requirements directly: ```bash npx clawhub install cross-funding-arb --force pip install -r references/requirements.txt ``` ### Technical Analysis All Python dependencies use open-ended lower bounds. A future version satisfying the constraint can therefore be installed without having been reviewed with this Skill. No lock file, hashes, or upper bounds are provided. This is security-sensitive because the dependencies include code that: - Handles the Hyperliquid private key - Creates Ethereum signing accounts - Signs and submits exchange transactions - Parses the credential file - Performs authenticated network communication Python packages execute code during installation and import. A compromised upstream release or unexpectedly incompatible future version could therefore access credentials or modify trading behavior. No evidence of a currently malicious package or typographical dependency name was found. The confirmed issue is the absence of reproducible and integrity-verified dependency resolution. ### Attack Path 1. An attacker compromises an allowed future release of one dependency or its publication account. 2. The malicious package version still satisfies the `>=` constraint. 3. A new installation or upgrade resolves to that package. 4. Package installation or import executes attacker-controlled Python code. 5. When the Skill runs, the malicious dependency can access process environment variables and imported objects. 6. It can recover exchange credentials, alter signed requests, manipulate position sizes, or transmit financial data externally. ### Impact Assessment A successful supply-chain compromis ...[truncated 490 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (44)

YARA rule 'agent_skill_credential_exfiltration_webhook': AI agent skill credential harvesting followed by webhook or external exfiltration [agent_skills]

Critical
Category
YARA Match
Confidence
91% confidence
Finding

The YARA hit is driven by a meaningful combination: broad credential access from environment and unrelated local configs, followed by outbound messaging/network transmission. While this is not classic attacker-controlled webhook exfiltration, the behavior still crosses trust boundaries and can leak sensitive trading/account data through repurposed third-party bot credentials.

Content

Scanner excerpt · references/cross_funding.py (reported line 53)May include surrounding context.

python
�══════════════════════════════════

SCRIPT_DIR = Path(__file__).resolve().parent
CONFIG_PATH = SCRIPT_DIR / "config.json"


def load_config() -> dict:
    """Load config.json and return the full config dict."""
    with open(CONFIG_PATH) as f:
        return json.load(f)


def _env(key: str, default: str = "") -> str:
    return os.environ.get(key, default)


def _env_bool(key: str, default: bool = False) -> bool:
    v = os.environ.get(key, "")
    if not v:
        return default
    return v.lower() in ("true", "1", "yes")


def hl_private_key() -> str:
    k = _env("HL_PRIVATE_KEY")
    if not k:
        raise RuntimeError("HL_PRIVATE_KEY not set")
    return k


def hl_testnet() -> bool:
    return _env_bool("HL_TESTNET", default=False)


def hl_vault_address() -> str:
    return _env("HL_VAULT_ADDRESS")


def state_dir() -> Path:
    d = _env("STATE_DIR")
    return Path(d) if d else SCRIPT_DIR


def binance_api

Tainted flow: 'req' from os.environ.get (line 789, credential/environment) → urllib.request.urlopen (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 · references/cross_funding.py (reported line 772)May include surrounding context.

python
headers={"Content-Type": "application/json"},
    )
    try:
        urllib.request.urlopen(req, timeout=10)
        return True
    except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError):
        return False

Tainted flow: 'req' from os.environ.get (line 789, credential/environment) → urllib.request.urlopen (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 · references/cross_funding.py (reported line 799)May include surrounding context.

python
headers={"Content-Type": "application/json"},
    )
    try:
        urllib.request.urlopen(req, timeout=10)
        return True
    except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError):
        return False

Credential Access

High
Category
Privilege Escalation
Confidence
76% confidence
Finding

The README instructs users to place exchange private keys and API secrets into a local .env file for a live trading strategy. While common, this is still sensitive credential handling guidance; if the file is stored with weak permissions, synced, logged, or accidentally committed, an attacker could take over exchange accounts and execute trades or withdraw where permissions allow.

Content

Scanner excerpt · README.md (reported line 27)May include surrounding context.

bash
# OpenClaw
cp .env.example ~/.openclaw/skills/cross-funding-arb/references/.env
# 编辑 .env,填入 HL_PRIVATE_KEY, BINANCE_API_KEY, BINANCE_SECRET_KEY

# 可选:调整 references/config.json 中的风控参数

Credential Access

High
Category
Privilege Escalation
Confidence
80% confidence
Finding

The command set -a && . ./.env && set +a sources the .env file directly into the shell environment before running the bot. If the .env file is modified maliciously or contains shell metacharacters/commands rather than simple assignments, sourcing it can execute arbitrary shell code in the user's environment in addition to exposing secrets to subprocesses.

Content

Scanner excerpt · README.md (reported line 37)May include surrounding context.

bash
cd ~/.openclaw/skills/cross-funding-arb/references
set -a && . ./.env && set +a

python3 cross_funding.py status    # 查看当前状态
python3 cross_funding.py tick      # 单次 tick

Credential Access

High
Category
Privilege Escalation
Confidence
83% confidence
Finding

Embedding . ./.env inside an automated scheduled command means secrets are loaded repeatedly in a non-interactive execution path, expanding exposure and making compromise of the .env file especially dangerous. Any malicious modification to that file would be executed automatically on every scheduled run, combining credential exposure with recurring code execution risk.

Content

Scanner excerpt · README.md (reported line 53)May include surrounding context.

md
--name "cross-funding-tick" \
  --cron "*/5 * * * *" \
  --session main \
  --system-event "cd $SKILL_DIR && set -a && . ./.env && set +a && python3 cross_funding.py tick"

# 或系统 crontab
*/5 * * * * cd $SKILL_DIR && set -a && . ./.env && set +a && python3 cross_funding.py tick >> /tmp/cross_funding.log 2>&1

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · README.md (reported line 55)May include surrounding context.

unding.py status # 查看当前状态 python3 cross_funding.py tick # 单次 tick

text

### 4. Deploy

```bash
SKILL_DIR=~/.openclaw/skills/cross-funding-arb/references

# OpenClaw cron
openclaw cron add \
  --name "cross-funding-tick" \
  --cron "*/5 * * * *" \
  --session main \
  --system-event "cd $SKILL_DIR && set -a && . ./.env && set +a && python3 cross_funding.py tick"

# 或系统 crontab
*/5 * * * * cd $SKILL_DIR && set -a && . ./.env && set +a && python3 cross_funding.py tick >> /tmp/cross_funding.log 2>&1

Commands

CommandDescription
tick主循环:扫描 → 验证 → 开仓/维护
report日报:持仓、PnL、余额、费率
status当前状态(优先读缓存)

Risk Controls

ControlDescription
稳定性验证3+ 快照 + std_ratio < 0.3
深度验证实时费率 + 价格差 < 0.5% + 净 APR ≥ 10%
保守预算min(两所) × 50%,budget=0 自动读取账户余额
�

Credential Access

High
Category
Privilege Escalation
Confidence
83% confidence
Finding

The system crontab example also sources .env directly, which is particularly risky because cron executes unattended and often with a predictable environment. A tampered .env could both leak exchange credentials and run arbitrary shell commands on a persistent schedule, worsening blast radius in a host compromise scenario.

Content

Scanner excerpt · README.md (reported line 56)May include surrounding context.

--system-event "cd $SKILL_DIR && set -a && . ./.env && set +a && python3 cross_funding.py tick"

或系统 crontab

*/5 * * * * cd $SKILL_DIR && set -a && . ./.env && set +a && python3 cross_funding.py tick >> /tmp/cross_funding.log 2>&1

text

## Commands

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
entrypoint: references/cross_funding.py

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
entrypoint: references/cross_funding.py

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
entrypoint: references/cross_funding.py

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 · SKILL.md (reported line 200)May include surrounding context.

bash
# 单次 tick
cd ~/scripts/cross-funding && set -a && . ./.env && set +a && python3 cross_funding.py tick

# 日报
python3 cross_funding.py report

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 · SKILL.md (reported line 349)May include surrounding context.

bash
# 单次 tick
cd ~/scripts/cross-funding && set -a && . ./.env && set +a && python3 cross_funding.py tick

# 日报
python3 cross_funding.py report

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 · SKILL.md (reported line 353)May include surrounding context.

bash
# 单次 tick
cd ~/scripts/cross-funding && set -a && . ./.env && set +a && python3 cross_funding.py tick

# 日报
python3 cross_funding.py report

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 · SKILL.md (reported line 366)May include surrounding context.

bash
# 单次 tick
cd ~/scripts/cross-funding && set -a && . ./.env && set +a && python3 cross_funding.py tick

# 日报
python3 cross_funding.py report

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 · SKILL.md (reported line 386)May include surrounding context.

bash
# 单次 tick
cd ~/scripts/cross-funding && set -a && . ./.env && set +a && python3 cross_funding.py tick

# 日报
python3 cross_funding.py report

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 · SKILL.md (reported line 397)May include surrounding context.

bash
# 单次 tick
cd ~/scripts/cross-funding && set -a && . ./.env && set +a && python3 cross_funding.py tick

# 日报
python3 cross_funding.py report

Credential Access

High
Category
Privilege Escalation
Confidence
92% confidence
Finding

This agent-facing cron command loads live credentials from .env and instructs the system to summarize the full report output back to a channel. Even if the command does not directly print secrets, the combination of credentialed execution and broad output forwarding increases the chance of leaking balances, positions, or other sensitive account data through the agent pipeline.

Content

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

--cron "0 0 * * *"
--tz "UTC"
--session isolated
--message "执行跨交易所资金费率套利日报: cd $SKILL_DIR && set -a && . ./.env && set +a && python3 cross_funding.py report。将完整输出结果总结后回复我。"
--announce
--channel discord

text

Credential Access

High
Category
Privilege Escalation
Confidence
92% confidence
Finding

The agent-mode daily report command runs with loaded credentials and asks the agent to summarize the complete output back to the user. That creates an avoidable path for sensitive account data exposure and broadens access to information derived from privileged APIs.

Content

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

日报: 每天 00:00 UTC

zeroclaw cron add --expr "0 0 * * *" --agent
"执行跨交易所资金费率套利日报: cd $SKILL_DIR && set -a && . ./.env && set +a && python3 cross_funding.py report。将完整输出结果总结后回复我。"

text

### Manual

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The code harvests Telegram and Discord credentials from unrelated local daemon configs and then uses them for outbound notifications. In a local agent environment this creates a serious cross-skill secret-boundary violation, because a trading skill can repurpose credentials belonging to other applications and transmit sensitive trading/account information through them.

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 · references/cross_funding.py (reported line 3956)May include surrounding context.

python
from dotenv import load_dotenv

    script_dir = Path(__file__).resolve().parent
    load_dotenv(script_dir / ".env")

    parser = argparse.ArgumentParser(
        description="Cross-exchange funding rate arbitrage (HL + Binance)"

Rp1

Medium
Category
MCP Rug Pull
Confidence
82% confidence
Finding

The README instructs users to run npx clawhub install cross-funding-arb --force without pinning a specific package version. This creates a supply-chain risk: users may fetch whatever version is current at execution time, including a compromised or typosquatted release, and the --force flag further reduces safety friction.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This README provides direct setup and deployment steps for an automated live-trading bot, including credential configuration and cron-based execution, but does not include an explicit warning that the commands can trade real funds and incur immediate financial loss. In this context, omission of a prominent safety warning materially increases the chance of unsafe operation by users who may assume a dry-run or low-risk mode exists.

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 · README.md (reported line 55)May include surrounding context.

--session main
--system-event "cd $SKILL_DIR && set -a && . ./.env && set +a && python3 cross_funding.py tick"

或系统 crontab

*/5 * * * * cd $SKILL_DIR && set -a && . ./.env && set +a && python3 cross_funding.py tick >> /tmp/cross_funding.log 2>&1

text

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill clearly requires sensitive environment variables, reads and writes state on disk, and performs networked trading and notification actions, yet it declares no explicit tool scope or permission boundaries. In an agent ecosystem, missing capability declarations reduces informed consent and weakens policy enforcement, especially for a skill that can place real orders and access credentials.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.