Back to skill

Security audit

Xia China Stock Analysis

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stock-analysis purpose, but its search fallbacks can run locally discovered external tools and it stores watchlist/analysis data locally without clear scoping, so it belongs in Review.

Review before installing. Use an isolated environment, pin dependencies, and disable or explicitly configure optional mcporter/Tavily search backends unless you trust those local tools. Expect stock symbols, company names, and search queries to be sent to external finance/search services and local watchlist/log files to retain stock-interest history.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T01 · Skill Instruction Hijacking

Note
Location
scripts/integrated_analysis.py:466
Finding

Hard-Coded Branding and Analyst Identity Injection in Generated Reports

Content
View full analysis

Vulnerability Details

File Location: scripts/integrated_analysis.py:466-473; templates/research_report_template.md:234-236
Vulnerability Type: Deterministic manipulation of user-facing output
Risk Level: Low

Evidence

scripts/integrated_analysis.py:466-473:

python
md += """
---

## ⚠️ 免责声明

本报告仅供参考,不构成投资建议。投资有风险,入市需谨慎。

---

*🦞 由虾总工综合分析系统生成*
*数据来源: 本地技术分析 + 东方财富妙想API*
"""

templates/research_report_template.md:234-236:

markdown
*报告日期:YYYY-MM-DD*
*分析师:虾总工 🦞*

Technical Analysis

The report generator unconditionally appends a fixed brand identity to every integrated report. The research template also identifies a fixed party as the analyst, regardless of who performed or requested the analysis.

This is a form of output manipulation because the attribution is not required to calculate technical indicators, retrieve market information, or produce a research report. It may also misrepresent authorship and the provenance of financial analysis. The behavior is deterministic and does not require a separate attacker-controlled input.

This finding does not alter the agent’s safety constraints, execute arbitrary code, or grant system privileges. Its scope is limited to the integrity and trustworthiness of generated content.

Attack Path

  1. A user requests an integrated stock-analysis report.
  2. The agent invokes integrated_analysis.py.
  3. generate_report() constructs the requested report.
  4. The function unconditionally appends the fixed brand and data-source attribution.
  5. The resulting report presents the fixed party as its producer, even when the user did not request that attribution.
  6. If the research template is used, the fixed analyst identity is similarly included in the output.

Impact Assessment

No operating-system privileges or additional data access can be obtained through this issue. The impact is confined to generated output and ...[truncated 275 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the hard-coded brand and analyst identity from generated reports and templates.
  2. Use neutral attribution such as “Generated by the stock-analysis tool” when attribution is necessary.
  3. Make any branding or analyst-name field explicitly configurable by the user.
  4. Do not claim a particular data source unless the runtime result confirms that the source was actually used.
  5. Add tests ensuring generated reports do not contain unrequested identity, promotional, or provenance claims.

T08 · Insecure Dependencies

Warning
Location
scripts/watchlist.py:2
Finding

Unpinned Dependencies and Runtime Package Resolution

Content
View full analysis

Vulnerability Details

File Location: scripts/watchlist.py:2-7; scripts/requirements.txt:1-6; SKILL.md:8-12
Vulnerability Type: Unbounded third-party dependency resolution
Risk Level: Medium

Evidence

scripts/watchlist.py:2-7:

python
# /// script
# requires-python = ">=3.10"
# dependencies = [
#     "yfinance>=0.2.40",
# ]
# ///

scripts/requirements.txt:1-6:

text
pandas>=1.5
numpy>=1.24
requests>=2.28
# Optional fallback sources (recommended):
# akshare>=1.10
# yfinance>=0.2

SKILL.md:8-12:

yaml
"install": [
  {
    "id": "pip-deps",
    "kind": "pip",
    "packages": ["pandas", "numpy", "requests"],
    "label": "Install Python dependencies"
  }
]

Technical Analysis

The project permits any future package release satisfying broad minimum-version constraints. It does not provide exact versions, hashes, or a lockfile. The documented uv run watchlist.py workflow can cause uv to resolve and install yfinance and its transitive dependencies at runtime.

Consequently, the code that executes may differ from the code reviewed during this audit. A compromised package release, malicious transitive dependency, dependency-confusion event, or unexpected incompatible update could execute arbitrary installation or import-time code with the privileges of the user running the Skill.

The audit did not identify a currently known malicious package in the declared dependency list. The vulnerability is the unsafe and non-reproducible resolution policy.

Attack Path

  1. An attacker compromises an allowed package or one of its transitive dependencies, or publishes a future release containing malicious code.
  2. The malicious release still satisfies a constraint such as yfinance>=0.2.40 or requests>=2.28.
  3. A user installs the Skill dependencies or invokes the documented uv run command.
  4. The resolver downloads the latest matc ...[truncated 776 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin every direct dependency to an exact reviewed version.
  2. Generate and commit a lockfile that includes all transitive dependencies.
  3. Require package hashes, for example through a hash-locked requirements file.
  4. Use an approved package index and disable untrusted supplemental indexes.
  5. Avoid runtime dependency installation in normal Skill execution.
  6. Install dependencies during a controlled deployment phase in an isolated virtual environment.
  7. Add automated dependency vulnerability and provenance scanning.
  8. Review dependency updates before changing the lockfile rather than accepting future releases automatically.

T07 · Tool Hijacking and Spoofing

Warning
Location
scripts/news_search.py:137
Finding

Implicit Execution of PATH-Resolved and Out-of-Package Search Tools

Content
View full analysis

Vulnerability Details

File Location: scripts/news_search.py:137-162; scripts/news_search.py:198-217
Vulnerability Type: Unsafe trust in externally resolved local tools
Risk Level: Medium

Evidence

scripts/news_search.py:137-162:

python
def is_available(self) -> bool:
    # 检查 mcporter 命令是否可用
    try:
        result = subprocess.run(
            ['mcporter', '--help'],
            capture_output=True,
            timeout=5,
            text=True
        )
        return result.returncode == 0
    except:
        return False

def search(self, query: str, max_results: int = 5) -> Optional[NewsSearchResult]:
    try:
        # 调用 mcporter
        result = subprocess.run(
            ['mcporter', 'call', 'zhipu-search.web_search_prime', '--arg', f'query={query}'],
            capture_output=True,
            timeout=30,
            text=True
        )

scripts/news_search.py:198-217:

python
def __init__(self):
    super().__init__("Tavily搜索", priority=3)
    self.tavily_script = Path(__file__).parent.parent.parent / "tavily-search-1.0.0" / "scripts" / "search.mjs"

def is_available(self) -> bool:
    return self.tavily_script.exists()

def search(self, query: str, max_results: int = 5) -> Optional[NewsSearchResult]:
    if not self.tavily_script.exists():
        return None

    try:
        # 调用 Tavily 脚本
        result = subprocess.run(
            ['node', str(self.tavily_script), query, '--max-results', str(max_results)],
            capture_output=True,
            timeout=30,
            text=True
        )

Technical Analysis

The Zhipu backend invokes mcporter by name and therefore trusts the process PATH to select the executable. The availability check itself executes the resolved binary. If a malicious executable appears earlier in PATH, it will run before any search request is made.

The Tavily backend ...[truncated 2290 chars]

Remediation
View remediation

Remediation Suggestions

  1. Do not automatically discover and execute optional external tools merely because they are present.
  2. Require explicit user or administrator configuration before enabling each external backend.
  3. Resolve mcporter to a configured absolute path rather than relying on PATH.
  4. Validate the canonical path, ownership, and permissions of external executables.
  5. Store required helper scripts inside the reviewed package or verify them using a pinned cryptographic hash or signature.
  6. Reject symbolic links and unexpected path traversal when validating helper-script locations.
  7. Run optional search backends in a restricted subprocess environment with a minimal environment, limited filesystem access, and controlled network access.
  8. Disclose which backend will receive each search query and allow users to disable external fallbacks.
  9. Preserve the current argument-array invocation and continue avoiding shell=True.
Vulnerability Patterns
  • 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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (39)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

This mismatch is more security-relevant because it indicates subprocess-based external search tools are invoked even though they are not disclosed in the declared behavior. Undocumented subprocess and network execution can expand the attack surface, surprise operators, and route data to third-party tooling that was never approved for the skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

This mismatch is more security-relevant because it indicates subprocess-based external search tools are invoked even though they are not disclosed in the declared behavior. Undocumented subprocess and network execution can expand the attack surface, surprise operators, and route data to third-party tooling that was never approved for the skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

This mismatch is more security-relevant because it indicates subprocess-based external search tools are invoked even though they are not disclosed in the declared behavior. Undocumented subprocess and network execution can expand the attack surface, surprise operators, and route data to third-party tooling that was never approved for the skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

This mismatch is more security-relevant because it indicates subprocess-based external search tools are invoked even though they are not disclosed in the declared behavior. Undocumented subprocess and network execution can expand the attack surface, surprise operators, and route data to third-party tooling that was never approved for the skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

This mismatch is more security-relevant because it indicates subprocess-based external search tools are invoked even though they are not disclosed in the declared behavior. Undocumented subprocess and network execution can expand the attack surface, surprise operators, and route data to third-party tooling that was never approved for the skill.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill advertises executable scripts, package installation, cron automation, and use of external data sources, but it does not declare any explicit tool scope or permissions boundaries. In an agent environment, that can lead to over-broad access to shell, network, and filesystem capabilities beyond what reviewers or operators expect, increasing the chance of unintended external calls or local state changes.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The activation language is very broad, causing the skill to trigger on generic market-trend or investment-research requests rather than narrowly scoped Chinese stock analysis tasks. Over-broad auto-invocation can expose users to unnecessary network calls, shell/script execution, or unintended use of file-backed watchlist behavior in contexts where the user did not request this skill.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The analysis output template is specified entirely in Chinese and implies the generated report should use that locale by default. There is no stated user opt-in or language selection mechanism, which can violate language/locale policy expectations when users have not requested Chinese output.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The module’s natural-language title, feature list, docstrings, and user-facing report strings are written exclusively in Chinese, which implies a fixed language experience. There is no indication of user opt-in, language selection, or documented justification for a Chinese-only locale constraint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The module writes persistent analysis logs to disk without any visible user-facing notice or consent mechanism. In an agent skill context, analysis steps may contain user queries, stock interests, intermediate results, or operational metadata, so undisclosed retention can create privacy exposure and enlarge the attack surface if local files are later accessed by other components or users.

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 file contains user-facing descriptions and output text in Chinese only, including the module docstring and CLI description. Under the policy rule, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is explicitly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

This code contains numerous user-facing strings in Chinese, including the module description and CLI output, with only limited fallback handling for encoding errors rather than a user-selectable language option. Under the policy rule, forcing a specific language without opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill is described as a stock analysis/data toolkit, but this data source manager checks availability of the Zhipu source by executing a local command (mcporter --help). Spawning subprocesses is not an obvious requirement for stock data fetching itself, and this source never actually returns market data in fetch, making the capability unjustified for the stated purpose.

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 · scripts/data_source_manager.py (reported line 342)May include surrounding context.

python
# 检查 mcporter 命令是否可用
        try:
            import subprocess
            result = subprocess.run(['mcporter', '--help'], capture_output=True, timeout=5)
            return result.returncode == 0
        except:
            return False

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code file contains natural-language user-facing descriptions and output strings in Chinese, and the CLI/help/report content appears to assume all users can read that language. Under the policy, forcing a specific language without user opt-in is a natural-language locale violation unless the restriction is documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code embeds user-facing descriptions and output strings exclusively in Chinese, including the module description and command-line messages, with no mechanism to select another language or confirm the user's preferred locale. That creates a natural-language locale policy issue because the skill effectively enforces a specific language without opt-in.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill's stated purpose is Chinese stock analysis and news aggregation, but this module implements news retrieval by invoking local executables (mcporter) and later a Node.js script rather than directly using in-process data APIs. Spawning local tools is a materially broader capability than ordinary market-data fetching and is not justified by the manifest description itself.

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 · scripts/news_search.py (reported line 143)May include surrounding context.

python
def is_available(self) -> bool:
        # 检查 mcporter 命令是否可用
        try:
            result = subprocess.run(
                ['mcporter', '--help'],
                capture_output=True,
                timeout=5,

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 · scripts/news_search.py (reported line 156)May include surrounding context.

python
def search(self, query: str, max_results: int = 5) -> Optional[NewsSearchResult]:
        try:
            # 调用 mcporter
            result = subprocess.run(
                ['mcporter', 'call', 'zhipu-search.web_search_prime', '--arg', f'query={query}'],
                capture_output=True,
                timeout=30,

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The Tavily backend reaches outside this module to locate and execute a separate search.mjs script via node. For a stock-analysis/news skill, calling arbitrary local scripts from another package is broader than the manifest's described analysis and aggregation behavior and introduces an execution capability not otherwise justified by the declared purpose.

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 · scripts/news_search.py (reported line 211)May include surrounding context.

python
try:
            # 调用 Tavily 脚本
            result = subprocess.run(
                ['node', str(self.tavily_script), query, '--max-results', str(max_results)],
                capture_output=True,
                timeout=30,

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The manifest describes a stock analysis toolkit centered on data retrieval, indicators, and reports, but this file also implements direct filesystem write capability via the optional output path. Persisting results to arbitrary local paths is beyond pure in-memory analysis/report generation and is not reflected in the manifest description for this skill file.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The file presents itself as a 'Stock Watchlist with Price Alerts', but signal-change checking invokes a separate script via subprocess using uv run analyze_stock.py. Launching subprocesses is a materially broader capability than maintaining a watchlist and checking stored price thresholds, and it is not disclosed in this file's documentation.

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 · scripts/watchlist.py (reported line 246)May include surrounding context.

python
if item.alert_on_signal:
            try:
                import subprocess
                result = subprocess.run(
                    ["uv", "run", str(Path(__file__).parent / "analyze_stock.py"), item.ticker, "--output", "json"],
                    capture_output=True,
                    text=True,

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The entire template is written in Chinese and prescribes Chinese section headings and content format, but it does not indicate that language selection is optional or limited to a region-specific use case. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.