Back to skill

Security audit

Ai Quant Trader

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a finance simulation skill rather than malware, but it needs Review because it can present synthetic trading data as analysis and has unsafe local file and install behavior.

Review carefully before installing. Treat all screening, backtest, strategy-performance, and signal output as simulation unless the publisher replaces random placeholders with validated data sources. Run any dependency installation in an isolated environment, avoid rerunning the registration script where existing backups matter, and do not connect this code to a real broker without adding explicit confirmations, path validation, audit logs, and hard trading limits.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (4)

T08 · Insecure Dependencies

Warning
Location
simple_fix.py:21
Finding
Unpinned Runtime Installation of Third-Party Packages## Vulnerability Details **File Location**: `simple_fix.py:21-37` **Vulnerability Type**: Unsafe dependency installation and supply-chain exposure **Risk Level**: Medium ### Vulnerable Code ```python def install_dependencies(): """安装依赖""" print("📦 安装必要依赖...") dependencies = [ "akshare", "pandas", "numpy", "tqdm" ] for dep in dependencies: print(f" 安装 {dep}...") try: subprocess.check_call([sys.executable, "-m", "pip", "install", dep, "--quiet"]) print(f" ✅ {dep} 安装成功") except subprocess.CalledProcessError: print(f" ⚠️ {dep} 安装失败,尝试继续...") ``` The same unsafe installation practice is recommended in `SKILL.md:15-18` and embedded in generated documentation at `register_with_openclaw.py:125-128`: ```bash pip install akshare pandas numpy ``` ### Technical Analysis The environment-repair utility installs packages from the default pip package index without exact version constraints, integrity hashes, a lock file, or an explicitly approved repository. Package versions and transitive dependencies can therefore change after the Skill has been reviewed. Python packages may execute installation or build logic, and imported packages execute module initialization code. Consequently, an upstream package compromise, malicious transitive dependency, or unexpectedly changed release could introduce arbitrary code into the environment. The package names shown are not demonstrated to be malicious; the vulnerability is the mutable and unauthenticated dependency-resolution process. ### Attack Path 1. An attacker compromises a listed package, one of its transitive dependencies, or the package-distribution account. 2. A malicious package release becomes eligible for normal pip resolution. 3. A user follows the documentation or runs `simple_fix.py`. 4. The script invokes pip using the current Python interpreter. 5. pip downloads and installs the mutable ...[truncated 651 chars]
Remediation
## Remediation Suggestions 1. Pin every direct dependency to a reviewed exact version. 2. Generate and commit a lock file that records transitive dependencies. 3. Require cryptographic hashes, such as through `pip install --require-hashes`. 4. Configure an explicitly approved package index or internal mirror. 5. Review dependency updates before modifying the lock file. 6. Move package installation out of the general environment-repair script and require explicit user approval. 7. Run installation in an isolated virtual environment with minimal filesystem and network privileges. 8. Add automated dependency vulnerability and provenance scanning.

T09 · Insecure Skill Coding Practices

Error
Location
strategy_gen.py:119
Finding
Path Traversal Through Unsanitized Strategy Names## Vulnerability Details **File Location**: `strategy_gen.py:119-133` **Vulnerability Type**: Path traversal leading to unauthorized JSON file access **Risk Level**: High ### Vulnerable Code ```python def optimize_strategy(self, strategy_name): """优化策略参数""" print(f"⚙️ 优化策略: {strategy_name}") strategy_file = os.path.join(self.strategies_dir, f"{strategy_name}.json") if not os.path.exists(strategy_file): return { "success": False, "error": f"策略不存在: {strategy_name}" } # 加载策略 with open(strategy_file, 'r', encoding='utf-8') as f: strategy = json.load(f) ``` The resulting path is later overwritten at `strategy_gen.py:159-161`: ```python # 保存优化后的策略 with open(strategy_file, 'w', encoding='utf-8') as f: json.dump(strategy, f, ensure_ascii=False, indent=2) ``` A second read primitive exists at `strategy_gen.py:199-207`: ```python def get_strategy(self, strategy_name): """获取策略详情""" strategy_file = os.path.join(self.strategies_dir, f"{strategy_name}.json") if not os.path.exists(strategy_file): return None with open(strategy_file, 'r', encoding='utf-8') as f: return json.load(f) ``` ### Technical Analysis `strategy_name` is directly interpolated into a filesystem path without rejecting directory separators, parent-directory components, absolute paths, or platform-specific path syntax. `os.path.join()` does not constrain the resulting path to `self.strategies_dir`. A value containing traversal sequences such as `../` can resolve outside `user_data/strategies`. Because the implementation appends `.json`, the target must have a compatible resulting filename. `get_strategy()` can disclose parseable JSON outside the intended directory. `optimize_strategy()` reads and subsequently rewrites an external JSON document if it contains the expected strategy fields. The command integration in the inspected `main.py` currently invokes these method ...[truncated 1429 chars]
Remediation
## Remediation Suggestions 1. Replace user-controlled filenames with server-generated opaque strategy identifiers. 2. If names must be accepted, enforce a strict allowlist such as `[A-Za-z0-9_-]+`. 3. Reject `..`, absolute paths, drive prefixes, forward slashes, backslashes, and null characters. 4. Resolve both the strategy root and candidate path before access: ```python root = Path(self.strategies_dir).resolve() candidate = (root / f"{strategy_name}.json").resolve() if candidate.parent != root: raise ValueError("Invalid strategy name") ``` 5. Open files only after containment validation. 6. Apply the same validation to `optimize_strategy()`, `get_strategy()`, and every future strategy file operation. 7. Run the Skill with filesystem permissions limited to its own data directories. 8. Add tests covering traversal sequences, absolute paths, Windows drive paths, encoded separators, and symbolic links.

T09 · Insecure Skill Coding Practices

Warning
Location
register_with_openclaw.py:34
Finding
Registration Recursively Deletes an Existing Backup Without Confirmation## Vulnerability Details **File Location**: `register_with_openclaw.py:34-40` **Vulnerability Type**: Unsafe destructive filesystem operation **Risk Level**: Medium ### Vulnerable Code ```python # 如果目标目录已存在,先备份 if target_dir.exists(): backup_dir = target_dir.with_name(f"{target_dir.name}_backup") if backup_dir.exists(): shutil.rmtree(backup_dir) shutil.move(target_dir, backup_dir) print(f"📦 已备份旧版本到: {backup_dir}") ``` The destination is hard-coded at `register_with_openclaw.py:18-27`: ```python # OpenClaw技能目录 openclaw_skills_dir = Path("C:/Users/Administrator/.openclaw/workspace/skills") if not openclaw_skills_dir.exists(): print(f"❌ OpenClaw技能目录不存在: {openclaw_skills_dir}") return False # 当前技能目录 current_skill_dir = Path(__file__).parent # 目标目录 target_dir = openclaw_skills_dir / "ai-quant-trader" ``` ### Technical Analysis When registration is repeated, the code unconditionally invokes `shutil.rmtree()` on the existing `ai-quant-trader_backup` directory. It does not request confirmation, create a uniquely named backup, inspect whether the directory contains user data, or provide a rollback mechanism. Because `rmtree()` recursively removes the entire directory tree, a previous installation backup and any data stored beneath it are permanently discarded before the current installation is moved into its place. The path is constructed from hard-coded constants rather than attacker-controlled input, so this is not a demonstrated arbitrary-directory deletion primitive. It is nevertheless an unsafe destructive operation against a predictable user workspace location. ### Attack Path 1. A previous registration has created `ai-quant-trader_backup`. 2. That backup contains an earlier Skill version, configuration, cache, or user-generated data. 3. The current `ai-quant-trader` target also exists. 4. The user reruns `register_with_openclaw.py`. 5. The script recursively deletes the existing backup without warning. 6. It moves the ...[truncated 515 chars]
Remediation
## Remediation Suggestions 1. Never overwrite or recursively delete an existing backup automatically. 2. Create timestamped or UUID-based backup directories. 3. Request explicit confirmation before any recursive deletion. 4. Display the fully resolved deletion path and validate that it is a direct child of the expected Skill directory. 5. Refuse to follow symbolic links during backup and cleanup operations. 6. Add backup-retention controls that default to preserving existing versions. 7. Use atomic staging and replacement so a failed registration can be rolled back. 8. Make the OpenClaw workspace path configurable and validate it rather than hard-coding an administrator profile. 9. Keep mutable user data outside versioned Skill installation directories.

other

Error
Location
stock_screener.py:96
Finding
Fabricated Financial Metrics and Trading Results Presented as Analysis## Vulnerability Details **File Location**: `stock_screener.py:96-108` **Vulnerability Type**: Fabricated financial analytics and nondeterministic trading output **Risk Level**: High ### Vulnerable Code The stock screener generates random fundamentals: ```python def get_financial_data(self, symbol): """获取财务数据(简化版)""" try: # 这里需要更复杂的财务数据获取 # 暂时返回模拟数据 return { 'ROE': np.random.uniform(-10, 20), # 模拟ROE 'current_ratio': np.random.uniform(0.3, 2.0), # 流动比率 'market_cap': np.random.uniform(10, 500) * 100000000, # 市值(元) } except: # 如果获取失败,返回默认值 return { 'ROE': 0, 'current_ratio': 1.0, 'market_cap': 10000000000, } ``` Those random values are used as screening criteria at `stock_screener.py:210-309`, including: ```python financials = self.get_financial_data(symbol) roe = financials['ROE'] if not (-20 < roe < 15): passed = False current_ratio = financials['current_ratio'] if current_ratio < 0.4: passed = False market_cap = financials['market_cap'] if market_cap >= 100 * 100000000: passed = False ``` Strategy performance is randomly generated at `strategy_gen.py:94-101`: ```python base_strategy["performance"] = { "win_rate": random.uniform(0.55, 0.75), "profit_factor": random.uniform(1.2, 2.0), "total_return": random.uniform(0.1, 0.3), "max_drawdown": random.uniform(0.08, 0.15) } ``` Backtest results are randomly generated at `strategy_gen.py:209-239`: ```python return { "success": True, "strategy_name": strategy_name, "symbol": symbol, "period": f"{days}天", "results": { "total_trades": random.randint(10, 30), "winning_trades": random.randint(7, 20), "losing_trades": random.randint(3, 10), "win_rate": round(random.uniform(0.6, 0.8) * 100, 1), "total_return": round(random.uniform(0.15, 0.35) * 100, 1), "annual_return": round(r ...[truncated 3205 chars]
Remediation
## Remediation Suggestions 1. Remove random values from all production screening, strategy, backtest, and automatic-trading paths. 2. Retrieve fundamentals from a documented, validated data source and record source timestamps. 3. Implement deterministic backtesting over actual historical data, including fees, slippage, survivorship bias, and data-adjustment policy. 4. Derive signals from explicit strategy conditions and verified prices rather than random selection. 5. Validate consistency among total, winning, and losing trade counts. 6. Clearly separate demo mode from production mode at the API and user-interface levels. 7. If synthetic data is retained, require explicit opt-in and label every response prominently as synthetic and unsuitable for investment decisions. 8. Block demo-generated results from automatic execution. 9. Add reproducibility tests and retain input datasets, strategy versions, parameters, and calculation logs. 10. Fail closed when required financial data is unavailable instead of supplying plausible-looking defaults.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (45)

Missing User Warnings

High
Confidence
96% confidence
Finding
When require_confirmation is set to false, the code directly submits buy and sell orders through the broker without any additional guardrails, user warning, policy check, or runtime authorization step. In the context of an auto-trading skill, this creates a materially dangerous pathway for unintended or manipulated trading activity, especially because the upstream signal generation is mock/random elsewhere in the file.

Missing User Warnings

High
Confidence
95% confidence
Finding
The skill can automatically submit a sell order for the entire position when a rule triggers, without any interactive confirmation, secondary authorization, or safety interlock. In a trading context, this is dangerous because malformed rules, stale price inputs, logic errors, or abuse by another component can cause irreversible liquidation and financial loss.

exec() call detected

High
Category
Dangerous Code Execution
Content
print(f"工作目录: {os.getcwd()}")
print(f"Python路径: {sys.executable}")
"""
        exec(test_code)
        
        return True
Confidence
85% confidence
Finding
Direct exec() call allows arbitrary code execution. An attacker can inject code that runs with the full privileges of the process.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The quick-start guide is entirely in Chinese and presents Chinese-only commands and examples without offering any language selection, fallback, or note about supported locales. This can exclude or mislead non-Chinese-speaking users, causing incorrect use of the skill or inability to understand trading-related guidance, but it does not by itself create code execution or direct security compromise.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The skill exposes broad natural-language trigger examples such as generic stock-analysis requests, which can overlap with ordinary conversation and cause unintended activation. In a trading context, accidental invocation can produce unsolicited investment guidance or strategy generation when the user did not explicitly intend to use the skill, increasing the risk of inappropriate financial actions based on mistaken context.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The phrase using the assistant name followed by a generic request is too vague to reliably separate ordinary chat from intentional skill invocation. Because this skill provides financial analysis and trading suggestions, ambiguous triggering is more dangerous than in a low-risk domain: a casual mention could elicit stock recommendations or risk settings without clear user intent.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The example trigger "帮我选今天值得关注的股票" is broad natural language that overlaps with ordinary conversational requests, making it easy for the skill to activate unintentionally when a user is just asking for general market commentary. In an agent ecosystem, overly generic invocation phrases can cause inappropriate routing into a finance/trading skill, leading to unsolicited stock screening or advice-like behavior in a higher-risk domain.

Vague Triggers

Medium
Confidence
90% confidence
Finding
Examples like "分析一下贵州茅台" and "600519的技术面怎么样" are extremely generic and can match routine user requests that do not clearly indicate consent to invoke a specialized trading-analysis skill. Because the skill operates in a financial decision-support context, accidental activation can expose users to unintended analytical output or strategy-like recommendations without explicit skill selection.

Intent-Code Divergence

Medium
Confidence
92% confidence
Finding
The module and class documentation claim this component is an 'automatic trading executor', which implies executing strategy-driven trading logic. However, the implemented signal detection in `check_signals` explicitly says it is temporary mock logic and then generates random buy/sell/hold signals, so the documented intent materially differs from the actual behavior.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The module docstrings and user-facing strings are entirely in Chinese, which implies a fixed language/locale experience. There is no indication that the user can opt into another language or that the locale restriction is documented as region-specific.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Content
print("\n检查基本模块:")
for module in ["json", "os", "sys", "datetime", "math"]:
    try:
        __import__(module)
        print(f"  ✅ {module}")
    except:
        print(f"  ❌ {module}")
Confidence
75% confidence
Finding
Dynamic __import__() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Content
print("\n检查基本模块:")
for module in ["json", "os", "sys", "datetime", "math"]:
    try:
        __import__(module)
        print(f"  ✅ {module}")
    except:
        print(f"  ❌ {module}")
Confidence
75% confidence
Finding
Dynamic __import__() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Content
print("\n检查基本模块:")
for module in ["json", "os", "sys", "datetime", "math"]:
    try:
        __import__(module)
        print(f"  ✅ {module}")
    except:
        print(f"  ❌ {module}")
Confidence
75% confidence
Finding
Dynamic __import__() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Content
print("\n检查基本模块:")
for module in ["json", "os", "sys", "datetime", "math"]:
    try:
        __import__(module)
        print(f"  ✅ {module}")
    except:
        print(f"  ❌ {module}")
Confidence
75% confidence
Finding
Dynamic __import__() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This code makes outbound requests to AKShare and writes retrieved data to local cache files without any explicit disclosure, consent flow, or control for the caller. In an agent skill context, silent network access and on-disk persistence can violate user expectations, leak sensitive usage patterns such as queried symbols and timestamps, and create compliance or privacy concerns even if the functionality is otherwise legitimate.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
Historical data retrieval similarly performs undisclosed external requests and persists returned data locally, which is a real transparency and privacy issue in an agent-integrated environment. While not code-execution or injection, it can expose user activity, consume network resources unexpectedly, and leave residual data on disk that other local users or processes may access.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The demo explicitly enables automatic trading through a command and presents it as a normal workflow step without any visible warning, confirmation gate, or discussion of financial risk. In a trading assistant context, this can normalize autonomous order execution and lead users to activate potentially unsafe behavior without understanding consequences such as losses, unintended orders, or strategy misconfiguration.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The code enables autonomous trading directly via `/自动 启用` without any confirmation step, explicit warning, or consent record that the system may act on the user's behalf. In a trading assistant context, this is safety-relevant because users may unintentionally authorize automated financial actions with real portfolio consequences, especially if downstream modules later connect to live brokerage APIs.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The module description is written as a Chinese-only instruction/context string ('OpenClaw集成模块 - 让AI量化交易助手可以直接在OpenClaw中使用'), and the rest of the user-facing metadata and command descriptions are also exclusively in Chinese. For a general integration module, this imposes a specific language/locale without offering the user any language selection or documenting a justified regional limitation.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The generated skill configuration defines only Chinese display text and slash commands such as '/交易', '/策略', and '/帮助'. This is a natural-language locale restriction presented as the only interface, with no user opt-in, fallback, or justification that the skill is intended solely for a Chinese-language environment.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The file's natural-language strings and documentation are entirely in Chinese, including the module description and class docstring, with no indication that language is configurable or chosen by the user. Under the stated policy, forcing a specific language without opt-in is a locale-policy concern.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The comment and branch label indicate an ATR stop-loss implementation, which implies use of historical price range or volatility data. Instead, the code explicitly states it is simplified and computes the threshold as a fixed percentage of cost price, which contradicts the documented trading logic rather than merely omitting detail.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The file’s user-facing natural-language content is entirely in Chinese, including the module description, status messages, and investment guidance, with no indication that the user can choose another language. This is a locale/language policy concern because the skill effectively imposes a specific language without explicit opt-in or a documented region-specific justification.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This Python file contains natural-language descriptions and runtime messages in Chinese, starting with the module docstring. The policy explicitly flags language or locale constraints when the skill forces a specific language without offering the user a choice or documenting a justified regional scope.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
for dep in dependencies:
        print(f"  安装 {dep}...")
        try:
            subprocess.check_call([sys.executable, "-m", "pip", "install", dep, "--quiet"])
            print(f"  ✅ {dep} 安装成功")
        except subprocess.CalledProcessError:
            print(f"  ⚠️  {dep} 安装失败,尝试继续...")
Confidence
89% confidence
Finding
The script automatically invokes pip to install packages from external package sources at runtime. This creates a supply-chain risk: if a dependency is compromised, typosquatted, or resolved from an unsafe index/configuration, running the script may execute untrusted package installation code on the host.

Static analysis

No suspicious patterns detected.