Back to skill

Security audit

实现基于qmt智能交易终端的A股交易数据本地化

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to be a real QMT stock-data downloader, but its local web dashboard and installation path expose users to avoidable control-plane and supply-chain risks.

Install only if you are comfortable running a local QMT-connected dashboard that can start, stop, and reconfigure downloads. Keep it bound to localhost, do not expose it on a network, avoid opening it while browsing untrusted sites, verify all external resource files and the xtquant source, and prefer pinned dependencies and local-only frontend assets before production use.

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

T09 · Insecure Skill Coding Practices

Error
Location
monitor.py:565
Finding

Unauthenticated State-Changing Web Endpoints and CSRF Exposure

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
templates/index.html:882
Finding

DOM-Based Stored Cross-Site Scripting in Dashboard State Rendering

Content
View full analysis
${state.current_stock}` : '暂无'; ``` ```javascript function updateErrorLogs(errors) { let container = document.getElementById('errorLogs'), badge = document.getElementById('errorBadge'); badge.innerText = errors.length; if(errors.length===0){ container.innerHTML = `

暂无错误

`; return; } let html = ''; errors.slice(-10).reverse().forEach(e => { html += `
${e.time||'--:--:--'} ${e.stock?`${e.stock}`:''}${e.message||''}
`; if (e.message && (e.message.includes('缺失') || e.message.includes('不存在'))) { if (!recentMissingMessages.includes(e.message)) { recentMissingMessages.push(e.message); if (recentMissingMessages.length > 3) { recentMissingMessages.shift(); } showMissingFileDialog(e.message); } } }); container.innerHTML = html; } ``` ```javascript function updateWarningLogs(warnings) { let container = document.getElementById('warningLogs'), badge = document.getElementById('warningBadge'); badge.innerText = warnings.length; if(warnings.length===0){ container.innerHTML = `
Remediation
View remediation

T03 · Remote Payload Retrieval and Execution

Warning
Location
templates/index.html:623
Finding

Runtime Retrieval and Execution of Remote Frontend Code Without Integrity Verification

Content
View full analysis
``` ```javascript function loadSocketIO() { return new Promise((resolve, reject) => { const localScript = document.createElement('script'); localScript.src = 'static/socket.io.min.js'; localScript.onload = resolve; localScript.onerror = () => { console.log('Socket.IO local version failed, loading from CDN...'); const cdnScript = document.createElement('script'); cdnScript.src = 'https://cdn.socket.io/4.5.0/socket.io.min.js'; cdnScript.onload = resolve; cdnScript.onerror = reject; document.head.appendChild(cdnScript); }; document.head.appendChild(localScript); }); } function loadBootstrapJS() { return new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = 'static/bootstrap-5.1.3.bundle.min.js'; script.onload = resolve; script.onerror = () => { console.log('Bootstrap JS local version failed, loa ...[truncated 2380 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned and Incomplete Python Dependency Specification

Content
View full analysis
=2.0.0 flask-socketio>=5.0.0 pandas>=1.3.0 psutil>=5.8.0 ``` The documented installation command is: ```bash pip install -r requirements.txt ``` The application also imports an undeclared dependency: ```python from xtquant import xtdata ``` ### Technical Analysis Every declared dependency uses an open-ended lower-bound constraint. As a result, installation at different times can resolve to different, unreviewed versions. Future major or minor releases may introduce incompatible behavior, newly disclosed vulnerabilities, or a compromised package version. No lock file or package hashes are provided, so installers cannot verify that downloaded distributions match artifacts reviewed by the project author. In addition, `agent.py` requires `xtquant`, but that package is absent from `requirements.txt`. This makes installation incomplete and may encourage users to obtain the missing component from an unofficial or unsafe source. No evidence was found that the listed package names are intentionally malicious. The finding concerns unsafe dependency management and mutable supply-chain behavior. ### Attack Path 1. A user follows the documented `pip install -r requirements.txt` instruction. 2. The package resolver selects the latest versions satisfying each `>=` constraint. 3. The selected artifacts differ from those originally tested or reviewed. 4. A compromised, vulnerable, or incompatible release is downloaded and installed. 5. Dependency code executes during installation or later when imported by the application. 6. For the undeclared `xtquant` dependency, a user may search for and install an unverified package from an unsafe source. ### Impact Assessment Python dependencies execute with ...[truncated 551 chars]
Remediation
View remediation
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
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (37)

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · main.py (reported line 302)May include surrounding context.

python
# 有管道输入
        instruction = sys.stdin.read().strip()
        if instruction:
            return instruction
    return None

def main():

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
94% confidence
Finding

This duplicate TM1 finding refers to the same unsafe shell-based launch at line 302. The main risk is unnecessary shell invocation for starting a local executable, which widens the attack surface without providing a legitimate benefit.

Content

Scanner excerpt · monitor.py (reported line 302)May include surrounding context.

python
# 假设 QMT 安装路径在配置中或固定
    qmt_path = r"C:\Program Files\XtMiniQmt\XtMiniQmt.exe"  # 需根据实际路径配置
    try:
        subprocess.Popen([qmt_path], shell=True)
        print(f"[QMT] 已启动: {qmt_path}")
    except Exception as e:
        print(f"[ERROR] 启动 QMT 失败: {e}")

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
94% confidence
Finding

This duplicate TM1 finding refers to the same unsafe shell-based launch at line 302. The main risk is unnecessary shell invocation for starting a local executable, which widens the attack surface without providing a legitimate benefit.

Content

Scanner excerpt · monitor.py (reported line 302)May include surrounding context.

python
# 假设 QMT 安装路径在配置中或固定
    qmt_path = r"C:\Program Files\XtMiniQmt\XtMiniQmt.exe"  # 需根据实际路径配置
    try:
        subprocess.Popen([qmt_path], shell=True)
        print(f"[QMT] 已启动: {qmt_path}")
    except Exception as e:
        print(f"[ERROR] 启动 QMT 失败: {e}")

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This duplicate TM1 finding refers to the config-driven shell launch at line 333. Because the program also exposes web endpoints that modify configuration, the surrounding skill context makes this more dangerous than a standalone local script: unsafe config trust can chain into process execution.

Content

Scanner excerpt · monitor.py (reported line 333)May include surrounding context.

python
print(f"[QMT] 正在启动: {exe_path}")
    try:
        # 使用 subprocess 启动,不等待完成
        subprocess.Popen(
            [exe_path],
            cwd=qmt_path,
            shell=True,

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This duplicate TM1 finding refers to the config-driven shell launch at line 333. Because the program also exposes web endpoints that modify configuration, the surrounding skill context makes this more dangerous than a standalone local script: unsafe config trust can chain into process execution.

Content

Scanner excerpt · monitor.py (reported line 333)May include surrounding context.

python
print(f"[QMT] 正在启动: {exe_path}")
    try:
        # 使用 subprocess 启动,不等待完成
        subprocess.Popen(
            [exe_path],
            cwd=qmt_path,
            shell=True,

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · templates/index.html (reported line 6)May include surrounding context.

html
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="source-map" content="disable"> <!-- 禁用source map以减少控制台警告 -->
    <title>股票数据下载监控</title>

    <!-- Bootstrap 5 CSS with inline fallback -->

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The trigger phrases include very generic requests such as “下载交易数据”, “获取历史数据”, and “下载历史数据”, which are likely to match ordinary user queries outside the intended narrow skill scope. This can cause the agent to invoke the skill unexpectedly, leading to over-broad activation, unintended tool usage, and possible exposure to risky side effects such as launching local software, downloading data, or modifying runtime state without sufficiently specific user intent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code emits user-facing logs, errors, progress, and completion messages entirely in Chinese across the skill, such as missing-file notices, progress updates, and task completion text. Because the file does not offer any user language selection or indicate that the skill is intentionally limited to Chinese-speaking users, it violates the language/locale policy for natural-language behavior.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The command-line help text says '下载股票日线数据' (download stock daily-line data), which implies a narrow function limited to stock daily data. However, the script accepts other periods such as 1m/5m/tick via the --period argument and, in download_all_data, processes both stock and index lists rather than stocks only.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

No manifest is available, so the skill's purpose is unknown. This file implements del_file, which permanently deletes arbitrary filesystem paths via os.remove, a destructive capability that is not justified by any stated purpose in the available documentation/context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The del_file function deletes an arbitrary file path via os.remove, but there is no confirmation prompt, docstring, or user-facing disclosure before the destructive operation. The only message appears after failure, so successful deletion happens silently.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

When overwrite=True, save_csv unconditionally calls del_file and then writes a new CSV, which can destroy existing user data. There is no visible warning, confirmation, or explanatory documentation indicating that existing files will be replaced.

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 · main.py (reported line 220)May include surrounding context.

python
print(f"[重要] 服务器将运行在端口 {selected_port},请访问 http://127.0.0.1:{selected_port}")
        
        # 运行monitor.py
        subprocess.run(cmd, check=True)
        
    except subprocess.CalledProcessError as e:
        print(f"[错误] 网页监控模式启动失败: {e}")

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The file contains user-facing logs, errors, help text, and status messages written exclusively in Chinese, indicating a fixed language/locale experience. There is no evidence in this file of user opt-in, locale selection, or documentation justifying a Chinese-only constraint.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The docstring for check_idle_and_shutdown describes graceful server shutdown behavior, but the implementation sets shutdown flags and then calls os._exit(0), which immediately terminates the process without normal cleanup. That is an intent-level contradiction because '关闭服务器' implies stopping the server, not unconditionally killing the whole process.

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 · monitor.py (reported line 291)May include surrounding context.

python
return True
    else:
        # 使用 tasklist 命令
        result = subprocess.run(['tasklist', '/FI', 'IMAGENAME eq XtMiniQmt.exe'],
                                capture_output=True, text=True)
        if 'XtMiniQmt.exe' in result.stdout:
            return True

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
93% confidence
Finding

This code launches an executable via subprocess.Popen with shell=True, which routes execution through the system shell. Even though the current path is hardcoded in this duplicate definition, using shell=True for process launch is unsafe and can become exploitable if the path or environment is influenced, especially on Windows where shell parsing and executable resolution can be abused.

Content

Scanner excerpt · monitor.py (reported line 302)May include surrounding context.

python
# 假设 QMT 安装路径在配置中或固定
    qmt_path = r"C:\Program Files\XtMiniQmt\XtMiniQmt.exe"  # 需根据实际路径配置
    try:
        subprocess.Popen([qmt_path], shell=True)
        print(f"[QMT] 已启动: {qmt_path}")
    except Exception as e:
        print(f"[ERROR] 启动 QMT 失败: {e}")

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

This process launch uses shell=True with exe_path and cwd derived from config.json, so a local attacker or any mechanism that can alter that config can influence what the shell executes. In this skill, the danger is increased because the application itself writes config.json and later trusts its contents to launch an external program, creating a clear path to arbitrary code execution under the monitor's privileges.

Content

Scanner excerpt · monitor.py (reported line 333)May include surrounding context.

python
print(f"[QMT] 正在启动: {exe_path}")
    try:
        # 使用 subprocess 启动,不等待完成
        subprocess.Popen(
            [exe_path],
            cwd=qmt_path,
            shell=True,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code rewrites config.json based on command-line arguments, but the write is only implied by implementation and lacks any confirmation prompt or explicit warning before modifying local files. Although a success message is printed afterward, there is no prior disclosure to the user that invoking this path will persist changes to disk.

Content

No source excerpt is available for this finding.

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
91% confidence
Finding

Setting cors_allowed_origins="*" allows any origin to interact with the Socket.IO service from a browser, weakening origin-based protections. In this file, that risk is amplified because the service exposes state-changing HTTP endpoints and real-time control/status functionality, so a malicious website could potentially drive user actions or pair with other weaknesses if the server is reachable.

Content

Scanner excerpt · monitor.py (reported line 521)May include surrounding context.

python
# 优化Socket.IO配置:禁用调试日志,减少启动开销
    socketio = SocketIO(
        app,
        cors_allowed_origins="*",
        logger=False,           # 禁用Socket.IO日志
        engineio_logger=False,  # 禁用Engine.IO日志
        ping_timeout=60,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The web API accepts user-supplied settings and persists them to config.json without any authentication, authorization, or CSRF protection visible in this file. In the context of this skill, this becomes more dangerous because configuration is later reloaded and used to control application behavior, including external process launch paths elsewhere in the program.

Content

No source excerpt is available for this finding.

Unbounded Resource Access

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Content

Scanner excerpt · static/bootstrap-5.1.3.bundle.min.js (reported line 6)May include surrounding context.

js
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
  */
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,(function(){"use strict";const t="transitionend",e=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?i.trim():null}return e},i=t=>{const i=e(t);return i&&document.querySelector(i)?i:null},n=t=>{const i=e(t);return i?document.querySelector(i):null},s=e=>{e.dispatchEvent(new Event(t))},o=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),r=t=>o(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(t):null,a=(t,e,i)=>{Object.keys(i).forEach((n=>{const s=i[n],r=e[n],a=r&&o(r)?"element":null==(l=r)?`${l}`:{}.toString.call(l).match(/\s([a-z]+)/i)[1].toLowerCase();var l;if(!new RegExp(s).test(a))throw new TypeError(`${t.toUpperCase()}: Option "${n}" provided type "${a}" but expected type "${s}".`)}))},l=t=>!(!o(t)||0===t.getClientRects().length)&&"visible"===getComputedStyle(t).getPropertyValue("visibility"),c=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),h=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?h(t.parentNode):null},d=()=>{},u=t=>{t.offsetHeight},f=()=>{const{jQuery:t}=window;return t&&!document.body.hasAttribute("data-bs-no-jquery")?t:null},p=[],m=()=>"rtl"===document.documentElement.dir,
...[truncated 27 chars]

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This local monitoring UI silently falls back to third-party CDNs for CSS if local assets fail, causing the browser to make external requests and trust remotely hosted code or styling. In an internal/admin dashboard context, that expands the trust boundary, leaks client metadata/IPs, and introduces supply-chain risk if the CDN asset is replaced or tampered with.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The CDN fallback occurs without any user-facing notice, so operators may believe the dashboard is purely local while it is actually contacting external services. That reduces informed consent and can violate privacy, network-segmentation, or compliance expectations for an internal monitoring tool.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The page dynamically injects Socket.IO and Bootstrap JavaScript from external CDNs when local files fail. Unlike CSS, remote JavaScript executes with full page privileges, so a compromised CDN or network path could run arbitrary script in the monitoring interface, access live state, invoke control actions, and interact with internal APIs.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.