Back to skill

Security audit

Stock Analysis CN

Security checks for vulnerabilities and agentic risk

Overview

The skill has no hidden backdoor, but it can generate investment recommendations from mock or placeholder data and uses unsafe local file-writing/cache behavior.

Install only for experimentation or code review. Do not rely on its investment recommendations without fixing the mock data paths, scoring calculation, ticker validation, output-path restrictions, and cache safety; never provide browser session cookies to it.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/utils.py:16
Finding
Predictable Shared Cache Permits Symlink Following and Path Traversal## Vulnerability Details **File Location**: `scripts/utils.py`, lines 16-22, 44-55, and 122 **Vulnerability Type**: Unsafe temporary-file and path construction **Risk Level**: High ### Vulnerable Code ```python # Cache directory CACHE_DIR = Path("/tmp/stock_analysis_cache") CACHE_DIR.mkdir(exist_ok=True) def cache_path(ticker: str, data_type: str, suffix: str = "json") -> Path: """Generate cache file path.""" return CACHE_DIR / f"{ticker}_{data_type}.{suffix}" ``` ```python cache_file = cache_path(ticker, f"kline_{days}") if is_cache_valid(cache_file): try: with open(cache_file, 'r') as f: return json.load(f) except: pass # Cache read failed, fetch fresh url = f"https://web.ifzq.gtimg.cn/appstock/app/fqkline/get?_var=kline_dayqfq&param={ticker},day,,,{days},qfq" try: resp = requests.get(url, timeout=10) ``` ```python with open(cache_file, 'w') as f: json.dump(result, f, ensure_ascii=False, indent=2) ``` ### Technical Analysis The cache uses a fixed, predictable directory under the globally shared `/tmp` hierarchy. The directory is created with `exist_ok=True`, but the code does not verify: - Whether an existing path is a real directory rather than a symlink. - Whether the directory is owned by the current process user. - Whether its permissions prohibit modification by other local users. - Whether an individual cache entry is a regular file rather than a symbolic link. The ticker is also directly incorporated into the cache path without format validation. Path separators and `..` components are therefore not rejected, allowing the resolved cache path to escape the intended directory in execution contexts where an attacker controls the ticker. Ordinary `open(..., 'w')` follows symbolic links and truncates the target. Consequently, a maliciously prepared cache entry can redirect a successful cache write to another file writable by the Skill process. Cache reads also follow symbolic lin ...[truncated 1932 chars]
Remediation
## Remediation Suggestions 1. Strictly validate ticker values before they reach either the URL or filesystem: ```python TICKER_PATTERN = re.compile(r"^(sh|sz)\d{6}$") def validate_ticker(ticker: str) -> str: if not TICKER_PATTERN.fullmatch(ticker): raise ValueError("Invalid ticker format") return ticker ``` 2. Validate `days` as an integer within the supported range, such as 1 through 320. 3. Use a per-user private cache directory rather than a predictable shared directory. Create it with mode `0700` and verify ownership. 4. Resolve every generated path and verify that it remains under the resolved cache root: ```python candidate = (CACHE_DIR / filename).resolve() candidate.relative_to(CACHE_DIR.resolve()) ``` 5. Reject cache paths that are symbolic links or non-regular files. 6. Open files using operating-system flags that prevent symlink following, such as `O_NOFOLLOW` where supported. 7. Write to a securely created temporary file in the same directory, flush and synchronize it, and then atomically replace the destination. 8. Do not silently accept an attacker-created cache directory. Verify that the directory is owned by the expected user and is not group- or world-writable.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/report_generator.py:202
Finding
Mock Financial Data and Inflated Scoring Produce Misleading Investment Recommendations## Vulnerability Details **File Location**: `scripts/fundamental_analysis.py`, lines 60-76; `scripts/valuation_analysis.py`, lines 141-148; `scripts/report_generator.py`, lines 202-204 **Vulnerability Type**: Financial-output integrity failure **Risk Level**: High ### Vulnerable Code The fundamental-analysis path returns fixed test data instead of current financial statements: ```python # For now, return mock data for testing return { 'income_stmt': { 'revenue': 1000000, 'net_profit': 100000, 'gross_profit': 300000, }, 'balance_sheet': { 'equity': 500000, 'assets': 2000000, 'debt': 800000, 'current_assets': 400000, 'current_liabilities': 200000, }, 'cash_flow': { 'operating_cf': 120000, } } ``` The valuation path assigns fixed values to every unsupported non-bank ticker: ```python else: # Generic placeholder for non-bank stocks metrics.pe = 25.3 metrics.pb = 3.2 metrics.pe_5y_median = 24.1 metrics.pb_5y_median = 3.0 metrics.industry_pe_median = 22.5 metrics.industry_pb_median = 2.8 ``` The report generator then multiplies an already 0-to-10 component-score average by ten: ```python total_score = sum(comp_scores.values()) / len(comp_scores) * 10 recommendation = generate_recommendation(total_score, comp_scores) ``` ### Technical Analysis The Skill presents itself as a data-driven stock-analysis system, but important report fields are derived from static or mock values without a machine-readable indication that the data is synthetic. The component scores produced by `generate_score_components()` are already expressed on a 0-to-10 scale. Their arithmetic mean is therefore also on a 0-to-10 scale. Multiplying that average by ten changes the range to 0-to-100, while `generate_recommendation()` continues to compare it against thresholds intended for a 0-to-10 score. For example, four neutral component scores of `5.0` produce ...[truncated 2114 chars]
Remediation
## Remediation Suggestions 1. Correct the score calculation by removing the additional multiplication: ```python total_score = sum(comp_scores.values()) / len(comp_scores) ``` 2. Add unit tests covering every recommendation boundary, including scores immediately below, equal to, and above 4.0, 5.0, 6.5, and 8.0. 3. Remove mock financial statements from production analysis paths. Keep test fixtures in a dedicated test module. 4. Return an explicit unavailable-data result when real financial data cannot be obtained: ```python { "available": False, "source": None, "reason": "Financial statements are unavailable" } ``` 5. Do not generate buy, hold, or sell recommendations when required inputs are unavailable, stale, synthetic, or insufficient. 6. Attach provenance to every metric, including the source, retrieval time, reporting period, whether the value is estimated, and whether it is static. 7. Clearly label any benchmark approximation in both structured output and rendered reports. Never present a generic placeholder as the current value for a specific ticker. 8. Require a minimum data-completeness threshold before calculating a composite score. 9. Add schema validation so that mock, missing, or stale values cannot silently enter the production recommendation pipeline. 10. Review the remaining financial calculations for correctness before using the Skill for real investment decisions.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (38)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
声明描述的是一个完整的A股投资分析与报告生成工具,但实际代码仅包含一个简单的 main() 函数并打印示例文本,且注释明确表示这是占位脚本、待后续实现。因此代码的实际行为与声明用途存在明显且实质性的不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
声明描述的是一个功能完整的A股综合分析与报告生成工具,覆盖技术面、估值、风险、基本面,并能输出Word投资报告。但提供的代码只是 fundamental_analysis.py,且是一个未完成的基本面分析模块。get_financial_statements 明确写明“Currently not implemented”,返回的是 mock data;calculate_metrics 中实际计算逻辑被注释掉,因此大多数指标不会生成;generate_summary 只会在少数指标存在时输出文字,否则返回“数据不足”。代码中没有技术指标计算、风险评估逻辑、行业估值基准实现,也没有Word文档生成功能。数据源层面虽然文档字符串提到腾讯财经API和东方财富API,但实际没有发起任何API请求。综合来看,代码实际行为与声明的主要用途存在明显且实质性的差异。

Tp4

High
Category
MCP Tool Poisoning
Confidence
87% confidence
Finding
整体上,代码的核心用途与描述较为接近:确实整合了技术面、估值、风险和基本面分析,调用腾讯相关K线获取价格,并生成一份投资分析报告,也包含行业估值基准对比。因此不存在完全不同的主用途。主要不一致在于“自动生成Word投资报告”这一点:代码使用的是 analysis_report.md / analysis_report_simple.md 模板,返回内容也是字符串;即使通过 --output 保存,也只是按文本写出,没有任何生成 .doc/.docx 或 Word 专有格式处理逻辑。另一个较小的不一致是描述强调“A股”,而代码入口和注释写的是 stock/ETF analysis report,示例也为沪深300ETF,说明覆盖范围不止A股个股。不过这属于范围表述偏差,严重性低于Word格式不符。综合判断为存在描述与实际行为不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
声明描述的是一个完整的A股投资分析与报告生成能力集合,包含技术面、估值、风险、基本面及Word报告输出。实际代码只是 risk_analysis.py 单一模块,主要从腾讯财经API获取价格数据并计算风险指标,属于声明中“风险”部分的一个子集。代码没有显示任何技术指标计算、财务基本面处理、行业专用估值基准、Word文档生成或完整报告拼装流程。因此描述显著夸大了该代码块的实际能力,属于明显不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
声明描述的是一个面向A股的全覆盖分析与报告生成能力,而代码片段实际是一个screening模块,核心功能是根据若干因子对股票/ETF候选池进行过滤和打分排序。它没有生成Word文档,也没有实现完整的技术面、风险、基本面综合分析报告。代码中的很多支持因子仅出现在注释或预设权重中,但实际enrich_with_metrics只填充了少量字段:成交量、1/3/6月收益、PE/PB、极少数模拟ROE;诸如ROA、负债率、现金流质量、波动率、beta、最大回撤、营收CAGR等并未真正计算。数据获取方面,Universe主要来自本地CSV文件,腾讯接口只用于K线历史价格,不足以支撑声明中的“基于腾讯财经API全覆盖分析”。因此该代码与声明在主要目的和实际能力上存在明显不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
该代码与声明存在明显不匹配。声明描述的是一个覆盖技术面、估值、风险、基本面的完整A股分析与Word报告生成工具;但提供的代码块仅是 technical_analysis.py,功能集中在拉取腾讯财经K线数据并进行技术指标计算与趋势总结。虽然“基于腾讯财经API”的部分基本吻合,但其余核心承诺——估值、行业估值基准、风险分析、基本面覆盖、Word报告生成——在此代码中均未体现。因此从描述与实际行为对比看,代码实际能力显著少于声明的主要用途。

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
声明描述的是一个功能完整的A股一键分析与报告生成技能,但实际代码仅是底层辅助工具的一部分。已实现内容主要是腾讯财经K线抓取、缓存和基础数学工具,这与“基于腾讯财经API”部分部分一致;然而技术面、估值、风险、基本面全覆盖分析和Word报告生成等核心承诺在该代码中并未实现。代码也没有显示任何行业估值基准逻辑。不存在明显额外的未声明敏感能力,但该片段的实际能力明显弱于声明,属于描述与行为不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
声明描述的是一个覆盖多维度投资分析并生成Word报告的完整A股分析工具,还特别强调基于腾讯财经API。实际代码只包含 valuation_analysis.py,一个单独的估值分析模块,且实现明显为简化版:历史估值数据函数直接返回空,主要数据来自硬编码银行样例和通用占位值,输出只是字典和文本摘要。虽然“估值分析”这一小部分与声明存在部分重合,但整体主功能范围远小于声明,且关键能力(技术面、基本面、风险、Word报告、腾讯财经API接入)均未体现,因此属于明显的描述与行为不一致。

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill advertises capabilities that imply network access and local file read/write, but it does not declare any explicit tool scope or permissions boundary. In an agent environment, undeclared capabilities reduce transparency and policy enforcement, increasing the chance that the skill performs external requests or writes files without the user's informed consent.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill describes use of external finance APIs and web scraping but does not clearly warn users that their prompts or requested tickers may trigger third-party network requests. In agent settings, undisclosed outbound retrieval can leak user interest, trading intent, or other sensitive context to external providers and makes data provenance and privacy harder to assess.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The entire report template, including headings, labels, and disclaimer text, is written only in Chinese. This creates a language/locale constraint without any visible opt-in or alternative, which matches the policy concern for forced language output.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The template content, section headings, labels, and disclaimer are entirely written in Chinese, which imposes a specific language/locale by default. Under the policy, language constraints should be user-selectable or clearly justified; this file provides neither an opt-in nor a documented region-specific rationale.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The document claims the skill does not require personal login, yet it also describes authenticated access to Jisilu via browser automation or a session cookie. This inconsistency can mislead users and implementers into handling authentication material when they may not expect it, increasing the chance of insecure credential collection or use.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
Suggesting that users provide a session cookie exposes a reusable authentication token that can grant account access and facilitate session hijacking. Even though the text says this is 'not recommended for security,' it still documents the practice as an option without strong prohibition or secure handling requirements.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The file gives direct trading implications such as 'Buy near support, sell near resistance' and breakout/breakdown cues without any warning that these are educational heuristics, not reliable investment advice, and that losses can occur. In the context of a skill marketed as one-click A-share analysis that auto-generates investment reports, this omission increases the chance users will over-trust the output and make risky financial decisions.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The function is documented as fetching real financial statements, but it returns hardcoded mock data instead. In an investment-analysis skill, this creates materially misleading outputs that can be mistaken for real analysis and may drive financial decisions based on fabricated data.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The main analysis entry point claims to perform full fundamental analysis, but it relies on placeholder inputs and a metrics calculator that leaves most fields unset. In the context of a stock-analysis skill that advertises comprehensive A-share analysis and report generation, this is dangerous because users may trust incomplete or fabricated analysis as investment-grade output.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The generated natural-language assessment uses fixed Chinese phrases such as "优秀", "良好", "偏低", and "数据不足" with no option for the user to select language or locale. This is a natural-language policy concern because the skill imposes a specific language in user-facing output rather than offering opt-in or documenting a justified region-specific limitation.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This Python file contains user-facing recommendation text exclusively in Chinese, and similar Chinese-only strings appear throughout the generated report. Because the skill does not provide any user opt-in or language/locale selection, it creates a natural-language locale policy concern under the language-choice requirement.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The CLI accepts an arbitrary --output path and writes the generated report there without any path restrictions or user-safety guardrails. In an agent/skill context, this creates an unintended filesystem side effect that can overwrite local files if an external caller or prompt controls the argument, which exceeds a pure 'analysis/report generation' capability.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The summary strings in `generate_summary` are written entirely in Chinese, and the file provides no option for users to select or opt into that locale. This can violate language/locale policy when the skill is used in broader contexts where user language preference is not guaranteed.

Intent-Code Divergence

Medium
Confidence
88% confidence
Finding
The top-level documentation lists quality, growth, momentum, low-volatility, and dividend factors such as ROA, Debt/Equity, CF quality, CAGR, beta, and volatility. In practice, enrich_with_metrics only computes volume, short-horizon returns, PE/PB, and a mocked ROE value for two tickers, while other listed factors are absent or explicitly marked as placeholders.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
This Python file contains user-facing strings in Chinese, and several function/docstring descriptions also assume a Chinese-language interface. Because the skill does not offer a language choice or explain that it is intentionally region-specific, it creates a locale policy concern under the language/locale rule.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The file-level docstring advertises a general 'Screening Module for Stocks and ETFs', but fetch_universe only looks for local ETF list CSV files and forcibly sets instrument_type to 'etf'. That means the default workflow does not actually implement stock-universe discovery despite claiming stock screening capability.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
Multiple summary strings and preset descriptions are written only in Chinese, which indicates the skill enforces a single language experience. The file does not expose any mechanism for language selection or document a justified regional limitation.

Static analysis

No suspicious patterns detected.