Back to skill

Security audit

小果股票量化分析助手

Security checks for vulnerabilities and agentic risk

Overview

This stock-analysis skill is not clearly malicious, but it handles account credentials insecurely and exposes deletion and custom-code features that need careful review.

Review before installing. Use this only with a trusted server and publisher, require HTTPS, avoid entering reusable passwords or auth codes unless the transport and logging are fixed, and do not let an agent call deletion or get_user_def_data without explicit human approval. Run bundled scripts only in a dedicated workspace because they can overwrite generated data files and accept file paths for formula conversion.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:5324
Finding

Authentication Credentials Transmitted over Plaintext HTTP in URL Parameters

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 5324-5327 and 5337-5374
Vulnerability Type: Plaintext credential transmission and sensitive data exposure
Risk Level: High

Vulnerable Code

python
self.password = password
self.auth_code = auth_code
self.base_url = f"http://{url}:{port}"
self.session = requests.Session()
self.timeout = 120
python
def _get_params(self, **kwargs) -> Dict[str, Any]:
    params = {
        'user': self.user,
        'password': self.password,
        'auth_code': self.auth_code,
    }
    params.update(kwargs)
    return params
python
url = f"{self.base_url}{endpoint}"
clean_params = {k: v for k, v in params.items() if v is not None}

try:
    if method.upper() == 'GET':
        response = self.session.get(
            url,
            params=clean_params,
            timeout=timeout
        )
    else:
        response = self.session.post(
            url,
            params=clean_params,
            timeout=timeout
        )

Technical Analysis

The documented API client constructs its base URL with the unencrypted http:// scheme. It then adds the username, password, and authorization code to the request parameter dictionary.

For GET requests, requests serializes these authentication values into the URL query string. The POST branch also uses params=clean_params rather than a protected request body or authorization header, so the credentials are still placed in the URL.

Plaintext HTTP provides neither transport confidentiality nor server authenticity. A network-positioned attacker can inspect or modify the traffic. Credential-bearing URLs may additionally be retained by reverse proxies, server access logs, monitoring systems, and error-reporting infrastructure.

Attack Path

  1. A user follows the instructions in SKILL.md and configures a real username, password, and authorization ...[truncated 1031 chars]
Remediation
View remediation

Remediation Suggestions

  1. Require HTTPS for every endpoint and reject configurations that use HTTP.
  2. Validate TLS certificates and hostnames using the platform's standard certificate verification.
  3. Move authentication values out of URL parameters.
  4. Prefer a short-lived bearer token in the Authorization header.
  5. If a request body is required, use an HTTPS-protected POST body rather than URL parameters.
  6. Avoid transmitting reusable account passwords on every request.
  7. Introduce token expiration, rotation, revocation, and least-privilege scopes.
  8. Review proxy and server logs for previously exposed credentials.
  9. Rotate any credentials that have already been used with this implementation.
  10. Add automated tests that reject plaintext endpoints and verify that generated URLs never contain sensitive fields.

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:5371
Finding

Credential-Bearing Request URLs Exposed through Default Console Logging

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 5371-5379
Vulnerability Type: Sensitive information exposure through logging
Risk Level: High

Vulnerable Code

python
if method.upper() == 'GET':
    response = self.session.get(url, params=clean_params, timeout=timeout)
else:
    response = self.session.post(url, params=clean_params, timeout=timeout)

if verbose:
    print(f"📤 Request URL: {response.url[:100]}...")
    print(f"📤 Status code: {response.status_code}")

The displayed English labels above correspond to the source's request URL and status-code logging statements; the executable expressions are unchanged.

Technical Analysis

The request parameter dictionary contains user, password, and auth_code. The requests library incorporates these values into response.url because both request branches pass them through the params argument.

Printing the first 100 characters is truncation, not redaction. Authentication fields are inserted before operation-specific parameters, making it plausible that some or all secret values will appear inside the printed prefix. The request method defaults to verbose=True, increasing the likelihood of exposure without an explicit user decision.

Console output can be captured by continuous-integration systems, Agent transcripts, notebook outputs, terminal logging, centralized observability platforms, or support records.

Attack Path

  1. A user initializes the API client with valid credentials.
  2. The user invokes an API method without disabling verbose output.
  3. The credentials are added to the request query string.
  4. The client prints the beginning of response.url.
  5. The output is retained in a terminal log, automated job log, Agent transcript, or monitoring platform.
  6. A person with access to that output retrieves the exposed authentication values.
  7. The credentials are replayed against the API.

Impact Ass

...[truncated 509 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove all logging of raw response.url values for authenticated requests.
  2. Change verbose logging to be disabled by default.
  3. If request diagnostics are necessary, log only the scheme, validated hostname, endpoint path, and status code.
  4. Implement structured redaction for password, auth_code, token, Authorization, and similar fields.
  5. Move authentication values to a protected authorization header so they never form part of the URL.
  6. Add tests asserting that console and application logs do not contain configured secret values.
  7. Restrict access to existing logs and purge any retained credential-bearing output.
  8. Rotate credentials that may already have appeared in logs or Agent transcripts.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/xg_tdx_func.py:402
Finding

Unrestricted File Overwrite and Unsafe Python Source Generation from Formula Input

Content
View full analysis

Vulnerability Details

File Location: scripts/xg_tdx_func.py, lines 402-434
Vulnerability Type: Arbitrary file overwrite and generated-code injection
Risk Level: Medium

Vulnerable Code

python
def params_data(test='test.txt',to_path='result.txt'):
    test=open(r'{}'.format(test),'r',encoding='utf-8')
    result=test.readlines()
    columns=[]
    for i in result:
        if ':' in i and ':=' not in i:
            name_list=i.split(':')
            columns.append(name_list[0])
    text=''.join(result)
    text1=text.replace(':=','=')
    text2=text1.replace(':','=')
    text4=text2.replace('&&',' and ')
    text5=text4.replace('||','or')
    text6=text5.replace('AND','and')
    text7=text6.replace('OR','or')
    text8=text7.replace('NOT','not')
    text9=text8.replace('DRAWNULL','None')
    text10=text9.replace(',NODRAW','')
    text11=text10.replace(
        'MF0>MF1 and MF0>MF2',
        'np.logical_and(MF0>MF1,MF0>MF2)'
    )
    text12=text11.replace(
        'MF0<MF1 and MF0<MF2',
        'np.logical_and(MF0<MF1,MF0<MF2)'
    )
    text3=text12.split(';')
    del text3[-1]
    fill=open(r'{}'.format(to_path),'w+',encoding='utf-8')
    fill.truncate()
    for i in text3:
        try:
            m=i.split('=')
            var=m[0]
            result=m[1]
            fill.write(var +'='+result)
        except:
           fill.write(var +'='+result)
    fill.write('\n')
    fill.write('return {}'.format(','.join(columns)))
    fill.close()

Technical Analysis

Both test and to_path are accepted directly from the caller and passed to open() without canonicalization, directory confinement, file-type checks, or overwrite confirmation. Opening to_path with w+ truncates an existing writable file immediately. A caller can therefore replace any file writable by the running process.

The function also treats formula content as t ...[truncated 2267 chars]

Remediation
View remediation

Remediation Suggestions

  1. Restrict input and output files to dedicated, application-owned directories.
  2. Resolve each path to its canonical form and verify that it remains beneath the approved directory.
  3. Reject absolute paths, traversal components, device paths, and symbolic-link escapes.
  4. Refuse to overwrite existing files unless the caller explicitly authorizes it.
  5. Write through a safely created temporary file and use an atomic rename only after validation succeeds.
  6. Parse formulas with a strict allowlisted grammar instead of performing string substitutions.
  7. Validate identifiers, functions, operators, argument types, and expression structure.
  8. If Python output is unavoidable, parse it with ast.parse and reject every node outside a minimal allowlist.
  9. Never automatically import or execute generated files.
  10. Run conversion in a low-privilege sandbox with narrowly scoped filesystem access.
  11. Replace broad exception handlers with explicit validation errors so malformed or hostile input cannot silently produce unsafe output.
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (42)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

该代码块聚焦于“因子计算与落盘”:从本地 parquet/Excel 文件读取历史行情、指数、基金代码、可转债代码,调用 xg_factor 中的方法批量计算因子,并将结果保存为 parquet/Excel/JSON,同时支持多进程、缓存、失败列表和检查点。它确实与‘股票因子数据/历史行情数据’部分相关,但与声明中列举的多项核心能力存在明显缺失,尤其是分钟数据、财务数据、指数数据服务接口、策略回测、组合分析等没有在代码中体现。另一方面,代码还处理基金与可转债,不仅限于股票。整体上,声明描述的是更完整的量化分析平台/助手,而代码只是其中一个离线因子计算模块,因此描述与实际行为存在实质性不匹配。

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill exposes destructive deletion operations for strategy data, including personal and community data, despite presenting itself as an analysis assistant. This increases the risk of accidental or malicious invocation leading to unauthorized or irreversible loss of user data.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

Documenting irreversible deletion endpoints without clear warnings or guardrails normalizes dangerous operations and increases the chance of accidental data destruction. In an assistant context, users may invoke such functions with incomplete understanding of permanence or scope.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

Bulk deletion of all simulated or community strategy data is a high-risk destructive capability with little justification for a stock analysis assistant. If triggered improperly, it can wipe large amounts of user content at once, magnifying impact compared with single-item deletion.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The get_user_def_data interface sends an arbitrary code string (func) to a remote endpoint for execution, effectively exposing remote code execution through the skill. In the context of an analysis assistant, this is especially dangerous because user-supplied Python can access files, secrets, network resources, or destructive library functions on the execution backend.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

In the single-threaded path, the branch labeled as asynchronous I/O preloading treats successfully loaded raw stock data as if factor computation had completed, then writes that raw dataframe directly into the final factor output location. This can silently replace expected derived factor datasets with incomplete data, corrupt downstream analysis, and mislead users into making financial decisions based on missing or wrong indicators.

Content

No source excerpt is available for this finding.

Whitespace Padding

High
Category
Prompt Injection
Confidence
80% confidence
Finding

Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Content

Scanner excerpt · references/xg_factor.txt (reported line 2029)May include surrounding context.

text
'''逆势操作 - AL'''
        cdp_val, ah_val, nh_val, nl_val, al_val = CDP_STD(CLOSE=self.C, HIGH=self.H, LOW=self.L)
        return al_val

Whitespace Padding

High
Category
Prompt Injection
Confidence
80% confidence
Finding

Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Content

Scanner excerpt · scripts/xg_factor.py (reported line 2029)May include surrounding context.

python
'''逆势操作 - AL'''
        cdp_val, ah_val, nh_val, nl_val, al_val = CDP_STD(CLOSE=self.C, HIGH=self.H, LOW=self.L)
        return al_val

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The activation list includes generic phrases such as “股票分析”, “股票数据”, and “股票策略”, which are broad enough to match many ordinary conversations about stocks rather than a narrowly scoped skill invocation. The description does not provide exclusion conditions, negative examples, or context limits to clarify when the skill should and should not activate.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The documentation instructs users to provide username, password, and auth_code to a remote HTTP service without prominently warning that credentials are being transmitted to an external server. Because the client uses plain HTTP in base_url construction, interception or misuse of credentials is a serious concern in this context.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest and top-level description focus the skill on stock historical data, stock factors, stock finance, index data, backtesting, and portfolio analysis. However, the file expands scope to '基金历史数据, 可转债历史数据' and '模拟交易和社区策略', and later includes concrete APIs for simulated/community strategy operations, which goes beyond the stated stock-analysis purpose.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This file contains natural-language identifiers, comments, and docstrings in Chinese throughout, beginning with the class description at L0019-L0020 and continuing across the file. Because the skill does not offer a language choice or document that it is intentionally region-specific, it effectively imposes a specific language/locale on users.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

CROSS_DOWN is documented as a death-cross check but uses the same crossing direction as CROSS_UP, so both methods can return identical semantics. In a trading library, this is more severe than a cosmetic bug because downstream rule engines may rely on both methods for opposite actions, leading to systematically broken execution logic.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

This code enables a force-recalculation mode that will recompute all stocks and overwrite existing output data, but the only disclosure is a console print after the mode is already active. The file performs repeated writes to parquet, Excel, and JSON outputs, making this a safety-relevant data-modifying operation that would benefit from an explicit pre-execution warning or confirmation before proceeding.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code comment says it is preloading data, but the implementation increments success counters and saves the preloaded dataframe as final output, creating a mismatch between operator expectations and actual behavior. This is dangerous because it hides a data integrity failure behind apparently successful processing, making detection difficult and enabling widespread propagation of incorrect results.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

params_data() accepts attacker-controlled input and output paths, reads an arbitrary local file, transforms its contents, and writes a generated Python-like file to an arbitrary destination. In an agent skill context, this expands capability from passive stock analysis into local filesystem modification, which can overwrite user files or drop executable code artifacts if exposed through tool calls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The code performs file creation/truncation and writes output without any user-facing disclosure, confirmation, or safety boundary. In a skill intended for quantitative analysis, silent writes are more dangerous because users reasonably expect computation, not mutation of local files, increasing the risk of unintended overwrites or covert artifact generation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The MACD_交易 docstring states 平空开多 is MACD crossing above 0 and 平多开空 is 0 crossing above MACD. However, the implementation assigns to 平空开多 twice and returns 平空开多 in both output positions, contradicting the documented intent of distinct buy/sell signals.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This Python skill contains natural-language descriptions and method names that force a specific language/locale for users, starting with the class docstring at L0019 and continuing throughout the file. The policy requires offering language choice or clearly documenting a justified locale constraint, neither of which appears here.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest describes this skill as providing stock factor data and quantitative analysis. However, in the async branch of cacal_all_stock_factor_single, the code calls get_stock_data and immediately writes that dataframe to 全部因子数据 without invoking any factor computation, so the produced output does not match the advertised factor-analysis behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The main script instantiates the trader with force_recalc=True and then immediately runs the full workflow, which can overwrite existing output files for all stocks. Although the class prints a warning when this mode is enabled, there is no confirmation prompt or protective check before the destructive batch write occurs from the default executable path.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The file defines formula-conversion helpers that read from an arbitrary local input path and write to an arbitrary local output path, which exceeds the stated stock-analysis/backtesting purpose. Even without code execution, this creates unnecessary filesystem access and can overwrite local files if exposed through the skill interface or downstream wrappers.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The params_data function accepts attacker-controlled file paths for both reading and writing via open(r'{}'.format(test), ...) and open(r'{}'.format(to_path), ...). This enables arbitrary local file read and overwrite within the agent runtime's permissions, which is risky and not justified by the declared analytics functionality.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The function name and docstring indicate a KDJ golden-cross signal, but the implementation returns CROSS(D, K), which is the opposite condition. In a stock trading skill, mislabeled buy/sell signals can directly invert trading decisions, causing financial loss or unsafe automation behavior in downstream strategies.

Content

No source excerpt is available for this finding.