Back to skill

Security audit

XTrade Futu Paper Trade

Security checks for vulnerabilities and agentic risk

Overview

This paper-trading skill is mostly coherent, but it needs Review because it can install mutable packages, submit a trading password to a configurable host, and place or cancel simulated orders without confirmation.

Install only if you are comfortable with a skill that can mutate its Python environment, contact FutuOpenD and AkShare-backed providers, and perform paper-trading order changes. Keep FUTU_HOST on a trusted local FutuOpenD endpoint, avoid using a reusable account password as FUTU_PASSWORD, do not run automated trading loops unattended, and prefer pinned dependencies or a prebuilt environment before use.

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

T08 · Insecure Dependencies

Error
Location
xtrade_futu_skill.py:56
Finding

Automatic Installation of Unpinned Third-Party Dependencies

Content
View full analysis

Vulnerability Details

File Location: xtrade_futu_skill.py:56-81, requirements.txt:1-2
Vulnerability Type: Supply-chain exposure through automatic installation of mutable dependency versions
Risk Level: High

Vulnerable code (xtrade_futu_skill.py:56-81):

python
def ensure_venv():
    if os.environ.get("FUTU_SKILL_VENV") == "1":
        return
    base_dir = Path(__file__).resolve().parent
    venv_dir = base_dir / ".venv"
    python_path = venv_dir / "bin" / "python"
    pip_path = venv_dir / "bin" / "pip"
    if sys.platform.startswith("win"):
        python_path = venv_dir / "Scripts" / "python.exe"
        pip_path = venv_dir / "Scripts" / "pip.exe"
    python_cmd = select_python()
    if python_path.exists():
        venv_version = get_python_version(str(python_path))
        if not is_compatible_python(venv_version):
            shutil.rmtree(venv_dir, ignore_errors=True)
    if not python_path.exists():
        subprocess.check_call([python_cmd, "-m", "venv", str(venv_dir)])
    if not pip_path.exists():
        raise RuntimeError("虚拟环境创建失败")
    requirements = base_dir / "requirements.txt"
    subprocess.check_call([str(pip_path), "install", "-r", str(requirements)])
    env = os.environ.copy()
    env["FUTU_SKILL_VENV"] = "1"
    subprocess.check_call([str(python_path), str(Path(__file__).resolve()), *sys.argv[1:]], env=env)
    sys.exit(0)

Mutable dependency declarations (requirements.txt:1-2):

text
futu-api>=1.0.0
akshare>=1.18.0

Technical Analysis

The Skill automatically invokes pip install whenever it starts outside the managed virtual environment. Both dependencies use lower-bound constraints rather than exact, reviewed versions. No lockfile, package hashes, or trusted-index enforcement is present.

Consequently, the effective code executed by the Skill can change without any modification to the audited repository. A new ...[truncated 1709 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin every direct and transitive dependency to an exact, reviewed version.
  2. Generate a reproducible lockfile containing cryptographic hashes for all supported platforms.
  3. Install with hash verification, such as pip install --require-hashes -r requirements.lock.
  4. Configure an explicitly trusted package index instead of silently accepting the user's ambient pip index configuration.
  5. Do not run dependency installation on every invocation. Separate installation from normal Skill execution and require explicit user approval before downloading packages.
  6. Record and verify the expected dependency manifest before launching the installed interpreter.
  7. Add automated dependency vulnerability scanning and controlled update review to the release process.
  8. Execute the Skill under a minimally privileged account with a restricted environment so a dependency compromise cannot access unrelated secrets.

T09 · Insecure Skill Coding Practices

Error
Location
xtrade_futu_skill.py:976
Finding

Trading Password Can Be Sent to an Arbitrary Environment-Configured Host

Content
View full analysis

Vulnerability Details

File Location: xtrade_futu_skill.py:151-155, xtrade_futu_skill.py:976-990, xtrade_futu_skill.py:993-1006
Vulnerability Type: Unvalidated remote endpoint used for sensitive credential submission
Risk Level: High

Endpoint construction (xtrade_futu_skill.py:151-155):

python
def open_contexts(host, port, trd_market):
    OpenQuoteContext, create_trade_context, _, _, _, _, _, _ = load_futu()
    quote_ctx = OpenQuoteContext(host=host, port=port)
    trade_ctx = create_trade_context(host, port, trd_market)
    return quote_ctx, trade_ctx

Credential retrieval and submission (xtrade_futu_skill.py:976-990):

python
def unlock_trade(trade_ctx):
    _, _, _, _, _, _, _, _ = load_futu()
    password = get_env("FUTU_TRADE_PWD", get_env("FUTU_PASSWORD", ""))
    if not password:
        json_out({"ok": False, "error": "缺少 FUTU_TRADE_PWD"}, 1)
    handler = find_trade_handler(trade_ctx, ("unlock_trade",))
    if handler is None:
        json_out({"ok": False, "error": "当前 futu-api 未提供交易解锁接口"}, 1)
    result = call_ctx_method(
        handler,
        [(["password", "pwd", "unlock_password"], password)],
        [password],
    )
    ret, data = result
    if ret != 0:
        json_out({"ok": False, "error": str(data)}, 1)

User-configurable host used before unlocking (xtrade_futu_skill.py:993-1006):

python
def cmd_order(args, side):
    host = get_env("FUTU_HOST", "127.0.0.1")
    port = int(get_env("FUTU_PORT", "11111"))
    trd_env = parse_trd_env(get_env("FUTU_TRD_ENV", "SIMULATE"))
    trd_market = parse_trd_market(get_env("FUTU_TRD_MARKET", "HK"))
    symbol = args.symbol
    price = float(args.price)
    qty = int(args.qty)
    order_type = args.order_type.lower()
    _, _, _, _, TrdSide, OrderType, _, _ = load_futu()
    quote_ctx, trade_ctx = open_contexts(host, port, trd_market)
    try:
        unlock
...[truncated 2544 chars]
Remediation
View remediation

Remediation Suggestions

  1. Enforce loopback destinations (127.0.0.1, ::1, or a securely resolved equivalent) by default for all operations that submit credentials.
  2. Reject non-loopback FUTU_HOST values unless a separate explicit option such as FUTU_ALLOW_REMOTE_HOST=1 is enabled.
  3. For remote operation, require an administrator-defined hostname allowlist and authenticated, encrypted transport with certificate or endpoint identity verification.
  4. Display or log the selected destination without exposing the password, and require explicit confirmation before the first credential-bearing connection to a remote endpoint.
  5. Remove the fallback from FUTU_TRADE_PWD to FUTU_PASSWORD so a general account password is not inadvertently used as the trading unlock secret.
  6. Keep the secret in process memory only for the shortest necessary period and ensure exceptions and debug output never serialize it.
  7. Document the trust boundary around FUTU_HOST, including the risk of environment-variable manipulation by wrappers, schedulers, and agent runtimes.
  8. Add tests confirming that buy, sell, and cancel reject unapproved remote hosts before reading or submitting the credential.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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 (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The manifest describes a limited paper-trading skill, but the documented behavior is substantially broader: it installs dependencies, manages orders, queries fills/funds/PnL, fetches historical market data, and pulls third-party financial data via AkShare. This mismatch is dangerous because reviewers and users may trust a narrower capability set than the skill actually exercises, leading to under-scoped approval and unexpected data access or account-impacting actions.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
96% confidence
Finding

The skill copies the full ambient environment and passes it into a child Python process. In agent and CI-like runtimes, environment variables often contain API keys, tokens, and other secrets; forwarding them wholesale to a subprocess broadens secret exposure and combines badly with the same function's runtime package installation and re-execution behavior.

Content

Scanner excerpt · xtrade_futu_skill.py (reported line 78)May include surrounding context.

python
raise RuntimeError("虚拟环境创建失败")
    requirements = base_dir / "requirements.txt"
    subprocess.check_call([str(pip_path), "install", "-r", str(requirements)])
    env = os.environ.copy()
    env["FUTU_SKILL_VENV"] = "1"
    subprocess.check_call([str(python_path), str(Path(__file__).resolve()), *sys.argv[1:]], env=env)
    sys.exit(0)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The buy/sell commands place orders immediately after parsing arguments and unlocking trading, with no confirmation prompt, dry-run mode, or policy guardrails. Even in paper trading, order placement is a sensitive action; in agent workflows, accidental or manipulated invocation can trigger unauthorized financial operations and normalize unsafe patterns that may later be reused against real trading contexts.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The cancel command performs an irreversible trading action without confirmation or secondary approval. In an agent environment, a single unintended invocation can disrupt strategy execution or interfere with active positions, making silent cancellation a meaningful integrity risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README explicitly promotes building a 'full-automatic AI trading system' and describes periodic monitoring followed by autonomous buy actions, but it does not provide a prominent warning that these commands can place orders and materially affect an account state. Even though the README says this is paper trading, autonomous order placement in a trading skill is still safety-sensitive because users or downstream agents may normalize unattended execution without understanding the operational and financial consequences.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill advertises shell and environment-dependent behavior but does not declare any explicit tool scope or permissions boundaries. In practice, this makes the skill capable of executing local commands, reading environment variables, and performing dependency installation without clear policy constraints, increasing the chance of unintended command execution or secret exposure.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill metadata frames the capability as quote/position/order paper trading, yet the body documents additional historical K-line and financial-statement retrieval features. This inconsistency weakens informed consent and security review because the effective data-access surface is larger than the declared purpose.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The trigger condition is broad: 'when the user needs quotes, positions, orders, fills, or placing orders, call this skill.' Without tighter scope boundaries or confirmation gates, an agent may invoke the skill too readily, including for sensitive trade-related actions, increasing the risk of unintended execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill includes buy, sell, and cancel operations but does not present an explicit warning or confirmation requirement for account-impacting actions. Even though it claims to restrict execution to paper trading, these are still state-changing financial operations, and weak UX safeguards can lead to unintended orders, cancellations, or over-trusting a similar pattern in future real-trading variants.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill expands into third-party financial data collection through AkShare and upstream data providers unrelated to the core paper-trading workflow. Adding external data sources increases network/data provenance risk, may expose user activity to additional services, and broadens the trust boundary beyond what the user expects from a Futu paper-trading skill.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · xtrade_futu_skill.py (reported line 13)May include surrounding context.

python
def get_python_version(python_cmd):
    try:
        output = subprocess.check_output(
            [python_cmd, "-c", "import sys; print(f'{sys.version_info[0]}.{sys.version_info[1]}')"],
            text=True,
        ).strip()

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file contains many user-facing error and next-step messages written only in Chinese, with no mechanism for users to choose language or locale. This creates a natural-language policy issue because the skill effectively forces a specific language for interaction without opt-in or documented regional justification.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill self-manages a virtual environment and installs packages at runtime, which is outside the minimal needs of a paper-trading skill and materially enlarges the execution and supply-chain attack surface. In an agent context, runtime environment mutation is especially risky because it can fetch and execute new code during normal use.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · xtrade_futu_skill.py (reported line 73)May include surrounding context.

python
if not is_compatible_python(venv_version):
            shutil.rmtree(venv_dir, ignore_errors=True)
    if not python_path.exists():
        subprocess.check_call([python_cmd, "-m", "venv", str(venv_dir)])
    if not pip_path.exists():
        raise RuntimeError("虚拟环境创建失败")
    requirements = base_dir / "requirements.txt"

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
93% confidence
Finding

The skill performs runtime dependency installation by invoking pip inside its own managed virtual environment. This executes package installation code and dependency resolution at run time, expanding the trust boundary to package indexes and local requirement contents, which is unnecessary for a paper-trading skill and can lead to code execution or supply-chain compromise.

Content

Scanner excerpt · xtrade_futu_skill.py (reported line 77)May include surrounding context.

python
if not pip_path.exists():
        raise RuntimeError("虚拟环境创建失败")
    requirements = base_dir / "requirements.txt"
    subprocess.check_call([str(pip_path), "install", "-r", str(requirements)])
    env = os.environ.copy()
    env["FUTU_SKILL_VENV"] = "1"
    subprocess.check_call([str(python_path), str(Path(__file__).resolve()), *sys.argv[1:]], env=env)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · xtrade_futu_skill.py (reported line 80)May include surrounding context.

python
subprocess.check_call([str(pip_path), "install", "-r", str(requirements)])
    env = os.environ.copy()
    env["FUTU_SKILL_VENV"] = "1"
    subprocess.check_call([str(python_path), str(Path(__file__).resolve()), *sys.argv[1:]], env=env)
    sys.exit(0)

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Adding AkShare introduces a second external data source and dependency chain unrelated to the stated Futu paper-trading function. That increases attack surface, trust assumptions, and data-flow complexity, especially since the fallback is automatic and may surprise users expecting only Futu-backed behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trade unlock password is sourced directly from environment variables without prominent disclosure, consent, or guidance about secret handling. In shared agent runtimes, environment variables are often broadly available to subprocesses and logs, so using them for a trading credential increases risk of credential exposure and unauthorized trade operations.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The implemented capability exceeds the declared purpose: besides quotes, positions, and paper orders, it exposes financial statement and indicator retrieval paths. Scope expansion matters in agent skills because users and orchestrators may grant trust based on the manifest, and undisclosed capabilities increase the chance of inappropriate data access or unintended invocation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

Nearly all user-facing instructions and descriptions are presented only in Chinese, and the README does not offer an English alternative or state that the skill is intentionally limited to Chinese-speaking users. This can violate language/locale policy expectations when no user opt-in or justified locale restriction is provided.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency specification uses a lower-bound only constraint, which allows installation of any newer version of futu-api, including releases with breaking changes or a compromised upstream package version. In a trading skill that queries market data and places paper trades, dependency drift can affect integrity of trading logic and increase supply-chain risk.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
futu-api>=1.0.0
akshare>=1.18.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency specification for akshare is unpinned and permits arbitrary newer versions to be installed, which can introduce malicious code, vulnerable transitive dependencies, or incompatible behavior without review. Because this skill operates in a financial context, unexpected library changes can impact data correctness and decision-making, making the supply-chain exposure more significant.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
futu-api>=1.0.0
akshare>=1.18.0

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · xtrade_futu_skill.py (reported line 179)May include surrounding context.

python
def find_quote_handler(quote_ctx, names):
    for name in names:
        if hasattr(quote_ctx, name):
            return getattr(quote_ctx, name)
    return None

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · xtrade_futu_skill.py (reported line 186)May include surrounding context.

python
def find_trade_handler(trade_ctx, names):
    for name in names:
        if hasattr(trade_ctx, name):
            return getattr(trade_ctx, name)
    return None

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · xtrade_futu_skill.py (reported line 266)May include surrounding context.

python
except Exception:
        return None
    for enum_name in enum_names:
        enum_cls = getattr(futu, enum_name, None)
        if enum_cls is None:
            continue
        for candidate in candidates: