Back to skill

Security audit

Finance Toolkit

Security checks for vulnerabilities and agentic risk

Overview

This A-share finance toolkit mostly matches its stated purpose, but it includes hidden local-code bridges and insecure market-data fetching that should be reviewed before installation.

Review before installing. Use it only if you are comfortable with Chinese A-share specific output, external market-data calls, and finance results that may be affected by unauthenticated HTTP data. Remove or disable the python_bridge.py exec path and system_bridge alert sync unless you explicitly need and trust those integrations, and avoid relying on this toolkit alone for trading decisions.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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 (3)

T07 · Tool Hijacking and Spoofing

Warning
Location
finance_toolkit/monitor_v3.py:207
Finding

Untrusted External System Bridge Can Be Imported and Executed

Content
View full analysis

Vulnerability Details

File Location: finance_toolkit/monitor_v3.py:207-212
Vulnerability Type: Untrusted local module loading and external notification invocation
Risk Level: Medium

Vulnerable Code

python
# 总线通知 — 集成到系统通信
try:
    import sys, os
    sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
    from system_bridge import SystemBridge
    if alerts:
        SystemBridge.monitor_notify_knowledge(alerts)
        print('📨 警报已同步到知识库')
except ImportError:
    pass

Technical Analysis

The script prepends the package's parent directory to sys.path and imports system_bridge, which is not included in the audited project. Python executes top-level code in a module as soon as it is imported. Consequently, the effective behavior of monitor_v3.py depends on an unbundled file found through a modified module search path.

This creates a local module-hijacking boundary: a file named system_bridge.py in the searched parent directory can execute arbitrary Python code under the identity of the user running the monitoring script. When alerts exist, the code also passes the generated alert records to the external module through SystemBridge.monitor_notify_knowledge(alerts).

The integration and its destination are not documented in SKILL.md, and the absent implementation prevents verification of its handling, storage, or transmission of alert data.

Attack Path

  1. An attacker or compromised installation process places a malicious system_bridge.py in the parent directory added to sys.path.
  2. A user directly runs finance_toolkit/monitor_v3.py.
  3. The script inserts the parent directory at the beginning of Python's module search path.
  4. Python resolves and imports the attacker-controlled system_bridge.py.
  5. Top-level malicious code executes immediately during import.
  6. If alerts were generated, the attacker-controlled monitor_notify_knowledge me ...[truncated 695 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the implicit sys.path modification and undeclared import.
  2. Package the bridge as an explicit, versioned dependency and import it through a stable package namespace.
  3. Make notification integration opt-in through an explicit configuration option.
  4. Before loading an optional plugin, resolve its path and verify that it is inside a trusted, read-only plugin directory.
  5. Define a narrow plugin interface and validate alert records before sending them.
  6. Document the notification destination, data fields, retention behavior, and network activity.
  7. Catch and report broader integration errors rather than silently suppressing only ImportError.
  8. If arbitrary plugins are required, execute them in a restricted subprocess with minimal filesystem and network permissions.

T09 · Insecure Skill Coding Practices

Warning
Location
finance_toolkit/astock_engine.py:44
Finding

Market Data Is Retrieved over Unencrypted HTTP

Content
View full analysis

Vulnerability Details

File Locations:

  • finance_toolkit/astock_engine.py:44-45, 101-102
  • finance_toolkit/strategy_engine.py:18-19
  • finance_toolkit/strategy_v4.py:20-25, 455-456
  • finance_toolkit/kline_report.py:69-76
  • finance_toolkit/fourier_analyzer.py:155-158

Vulnerability Type: Missing transport authentication and response-integrity protection
Risk Level: Medium

Vulnerable Code

finance_toolkit/astock_engine.py:44-45:

python
codes = ','.join(symbols)
url = f"http://qt.gtimg.cn/q={codes}"
data = self._curl(url)

finance_toolkit/astock_engine.py:101-102:

python
url = f"http://web.ifzq.gtimg.cn/appstock/app/fqkline/get?param={symbol},day,,{days}"
data = self._curl(url)

finance_toolkit/strategy_engine.py:18-19:

python
url = f"http://qt.gtimg.cn/q={','.join(symbols)}"
r = subprocess.run(['curl.exe','-s',url], capture_output=True, timeout=10)

finance_toolkit/strategy_v4.py:20-25:

python
url = f"http://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData?symbol={symbol}&scale=240&ma=no&datalen={days}"
r = subprocess.run(
    ['curl.exe','-s','-L','-e','http://finance.sina.com.cn',
     '-H','Referer: http://finance.sina.com.cn', url],
    capture_output=True, timeout=15)

finance_toolkit/kline_report.py:69-76:

python
url = (
    f"http://ifzq.gtimg.cn/appstock/app/fqkline/get"
    f"?param={symbol},day,,,{count},qfq"
)

try:
    r = subprocess.run(
        ['curl.exe', '-s', url, '-L', '--max-time', '15'],
        capture_output=True, timeout=20
    )

finance_toolkit/fourier_analyzer.py:155-158:

python
import json, urllib.request
url = 'http://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData?symbol=sz000009&scale=240&ma=no&datalen=500'
req = urllib.request.Request(url, headers={"User-Agent"
...[truncated 2101 chars]
Remediation
View remediation

Remediation Suggestions

  1. Replace every market-data URL with a supported HTTPS endpoint.
  2. Remove HTTP fallback behavior unless the user explicitly enables an insecure mode.
  3. For curl, add --proto '=https' and --proto-redir '=https' so redirects cannot downgrade transport security.
  4. Check subprocess return codes and reject incomplete or failed responses.
  5. Apply strict response-size limits before JSON decoding or parsing.
  6. Validate response schemas, stock identifiers, timestamps, numeric ranges, and chronological ordering.
  7. Compare high-impact signals against an independent HTTPS data source before producing trading alerts.
  8. Clearly mark data as unavailable when authenticity cannot be established rather than silently using insecure fallback data.
  9. Add automated tests that verify all production endpoint URLs use HTTPS.

T09 · Insecure Skill Coding Practices

Note
Location
finance_toolkit/kline_report.py:143
Finding

User-Controlled Stock Names Are Used in Report Paths Without Sanitization

Content
View full analysis

Vulnerability Details

File Location: finance_toolkit/kline_report.py:143-146
Related Write Sink: finance_toolkit/kline_report.py:174-186
Vulnerability Type: Improper pathname sanitization and output-directory containment
Risk Level: Low

Vulnerable Code

Path construction at finance_toolkit/kline_report.py:143-146:

python
# 构造文件名
safe_name = name if name else code
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"kline_{code}_{safe_name}_{ts}.png"
filepath = os.path.join(REPORT_DIR, filename)

The resulting path is passed to the chart writer:

python
mpf.plot(
    df,
    type='candle',
    style=s,
    title=title,
    ylabel='价格 (元)',
    ylabel_lower='成交量 (手)',
    volume=True,
    addplot=apds,
    savefig=dict(fname=filepath, dpi=120, bbox_inches='tight'),
    figsize=figsize,
    tight_layout=True,
)

The command-line entry point supplies the relevant values directly:

python
if len(sys.argv) > 1:
    code = sys.argv[1]
    name = sys.argv[2] if len(sys.argv) > 2 else ""
    days = int(sys.argv[3]) if len(sys.argv) > 3 else 60
    generate_kline(code, name, days)

Technical Analysis

The variable is named safe_name, but no sanitization is performed. Both code and name can originate from command-line arguments and may contain path separators or traversal components. The path is joined to REPORT_DIR without canonicalization or a subsequent containment check.

Because a fixed kline_ prefix precedes the user input, straightforward absolute-path replacement is not possible. Escaping the report directory generally requires a crafted value whose path components correspond to existing or attacker-created intermediate directories. This constraint lowers exploitability but does not provide a reliable security boundary.

The sink writes a generated PNG rather than attacker-selected arbitrary bytes, limiting the ...[truncated 1192 chars]

Remediation
View remediation

Remediation Suggestions

  1. Validate stock codes against a strict pattern such as ^[0-9]{6}$.
  2. Restrict stock names to an allowlist of safe Unicode letters, digits, spaces, hyphens, and underscores.
  3. Replace /, \, control characters, and traversal components before constructing the filename.
  4. Prefer a generated identifier for the physical filename and use the stock name only in chart metadata.
  5. Resolve both the report directory and destination path before writing:
    python
    report_root = os.path.realpath(REPORT_DIR)
    destination = os.path.realpath(os.path.join(report_root, filename))
    if os.path.commonpath([report_root, destination]) != report_root:
        raise ValueError("Invalid report path")
    
  6. Open output files with exclusive-creation semantics where possible to prevent unintended overwrites.
  7. Apply restrictive directory permissions and avoid writing reports under security-sensitive directories.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (43)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| 🎯 策略引擎 | `strategy_v4.py` | 多指标融合策略(布林带+RSI+KDJ+MACD) |

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The module claims to implement an SMA trading strategy, but it also conditionally reads and executes a sibling file via exec() and may re-launch itself under a different Python interpreter. This hidden bootstrap behavior is unrelated to the stated finance purpose, bypasses normal import transparency, and can execute arbitrary code from python_bridge.py with the user's privileges.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The module dynamically loads and executes python_bridge.py by reading the file and passing its contents to exec(), which grants arbitrary code execution at import/runtime. Because this is done conditionally and without disclosure, any modified sibling file can run unrestricted code under the user's account, making the strategy module an execution trampoline.

Content

No source excerpt is available for this finding.

Ssd 4

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The staged bootstrap first conditionally executes a sibling script and then may reroute execution to another Python interpreter, which obscures the true control flow of the module. In a finance-strategy context, this is especially dangerous because users expect deterministic analytical code, not hidden runtime pivots that can bypass scrutiny and execute arbitrary payloads.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The file-level description and all user-facing output strings are written exclusively in Chinese, indicating the skill is designed to operate in a fixed language without any opt-in or language selection mechanism. The policy requires not forcing a specific language or locale unless the constraint is clearly documented and justified or the user is given a choice.

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 · finance_toolkit/astock_engine.py (reported line 29)May include surrounding context.

python
def _curl(self, url, timeout=10):
        """通过curl获取数据"""
        try:
            result = subprocess.run(
                ['curl.exe', '-s', '--connect-timeout', str(timeout), url],
                capture_output=True, timeout=timeout+5
            )

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script contains an unrelated execution path that silently re-invokes itself through a hard-coded alternate Python interpreter when msys64 appears in sys.executable. In a backtesting tool, this hidden process hop expands the trust boundary, changes runtime behavior without disclosure, and could execute a different interpreter or environment than the user expects, increasing the chance of unsafe code execution or environment-based abuse.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

subprocess.run(['C:/Python314/python.exe'] + sys.argv) causes the script to transfer execution to another Python interpreter with the original arguments and no user-facing warning. This can bypass user expectations, execute under a different package set or security posture, and make auditing difficult because the effective runtime is not the one initially invoked.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

User-facing strings throughout the file, including the module description and printed report labels, are written in Chinese only. This enforces a specific language/locale for users without any opt-in, fallback, or explanation that the tool is intended solely for a Chinese-speaking or region-specific context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring states the report is a '每日A股市场分析报告' and all described output is in Chinese, with no indication that users can choose another language. This is a natural-language locale restriction and the file does not document an opt-in or a justified region-specific policy exception.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstrings, comments, and user-visible suggestion strings are written entirely in Chinese, and there is no option for users to select another language or any documented reason for a Chinese-only locale. The policy explicitly calls out language or locale constraints as violations when they are forced without user opt-in.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The top-level documentation says kds.dll/RingBuffer is embedded into the A-share strategy SMA calculation to replace pandas rolling().mean(), and the benchmark labels a path as 'C RingBuffer'. However, FastMAStrategy.run() instantiates SimpleSMA for both fast and slow averages, so the documented accelerated implementation is not what the strategy actually uses.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The module dynamically loads and executes python_bridge.py by reading the file and passing its contents to exec(), which grants arbitrary code execution at import/runtime. Because this is done conditionally and without disclosure, any modified sibling file can run unrestricted code under the user's account, making the strategy module an execution trampoline.

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 · finance_toolkit/kline_report.py (reported line 74)May include surrounding context.

python
)

    try:
        r = subprocess.run(
            ['curl.exe', '-s', url, '-L', '--max-time', '15'],
            capture_output=True, timeout=20
        )

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module description and user-facing text are written entirely in Chinese, and nothing in the file offers a language choice or explains that the skill is intentionally limited to Chinese-speaking users or a China-specific environment. Under the policy, forcing a specific language without opt-in is a natural-language locale violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The module description and all user-facing output strings are written exclusively in Chinese, and the skill provides no opt-in, language selection, or justification that it is intended only for a Chinese-speaking or region-specific audience. This is a natural-language policy issue because it imposes a locale on all users by default.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script performs an additional side effect beyond local monitoring by sending generated alerts into a separate knowledge-system bridge. Cross-system data propagation increases the attack surface and can leak trading signals, watchlist contents, or derived market intelligence into another component without clear user consent, configuration gating, or audit controls.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module description and all user-facing outputs are written specifically for A-share Chinese-market usage, e.g. "A股盯盘策略系统" and references to Chinese-market data only. The file provides no option for users to choose another language or locale, which is a natural-language locale policy issue under the stated rule.

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 · finance_toolkit/strategy_engine.py (reported line 19)May include surrounding context.

python
def batch(self, symbols):
        if isinstance(symbols, str): symbols = [symbols]
        url = f"http://qt.gtimg.cn/q={','.join(symbols)}"
        r = subprocess.run(['curl.exe','-s',url], capture_output=True, timeout=10)
        raw = r.stdout.decode('gbk', errors='ignore')
        results = {}
        for line in raw.strip().strip(';').split(';'):

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The function docstring says '回测分析(当前基于当日数据)', and the module header cites optimized parameters from a prior backtest, creating the expectation of historical-analysis behavior. In practice, the function immediately calls the live quote API for a single symbol and ignores the provided historical parameter days_data, so it performs only a current snapshot assessment rather than a real backtest.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The module title and all user-facing strings are in Chinese, and the script does not provide any opt-in or configuration for alternate languages. Under the stated policy, hard-coding a specific language without user choice is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

A financial analysis skill should typically perform computation in-process, but this file adds an unnecessary ability to invoke external executables and switch interpreters. In the skill context, that extra capability is more dangerous because it is unrelated to the core purpose and could be abused or fail unpredictably on user systems.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
84% confidence
Finding

The script conditionally re-executes itself via a hard-coded external Python interpreter and forwards all command-line arguments. While it does not use a shell, it unnecessarily expands execution capability and trusts the local environment/path layout, which is risky for an analysis skill that should not need process spawning just to function.

Content

Scanner excerpt · finance_toolkit/strategy_v4.py (reported line 8)May include surrounding context.

python
import sys, os, subprocess as _bridge_sh
if 'msys64' in sys.executable:
    _bridge_sh.run(['C:/Python314/python.exe'] + sys.argv)
    sys.exit(0)

import subprocess, json, pandas as pd, numpy as np

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
95% confidence
Finding

This code launches curl.exe as an external process to fetch remote market data, introducing command-execution capability where a normal HTTP client library would suffice. Although arguments are passed as a list, reducing shell injection risk, the design still increases attack surface through reliance on external executables and outbound network access over plain HTTP.

Content

Scanner excerpt · finance_toolkit/strategy_v4.py (reported line 21)May include surrounding context.

python
def _sina_kline(self, symbol, days=400):
        """新浪K线数据"""
        url = f"http://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData?symbol={symbol}&scale=240&ma=no&datalen={days}"
        r = subprocess.run(
            ['curl.exe','-s','-L','-e','http://finance.sina.com.cn',
             '-H','Referer: http://finance.sina.com.cn', url],
            capture_output=True, timeout=15)

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Using subprocess-launched curl.exe for data retrieval gives the skill command-execution capability that is unjustified for simple market-data fetching. In a finance skill, this makes the behavior more concerning because users expect analytics, not arbitrary process execution and opaque network tooling.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.