Back to skill

Security audit

股海罗盘 - A股股票量化分析

Security checks for vulnerabilities and agentic risk

Overview

This stock-analysis skill is not clearly malicious, but it needs review because it stores and transmits API keys riskily and forces paid upgrade links into analysis output.

Install only if you are comfortable with a Chinese-language, freemium stock-analysis tool that creates a persistent local API key, contacts external market-data and payment services, and inserts upgrade links in preview reports. Avoid using a valuable paid key until the publisher uses HTTPS for all credential-bearing calls, narrows payment-token generation to explicit upgrade flows, and documents key storage and rotation clearly.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (4)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:1325
Finding

Forced Promotional Output and Agent Response Hijacking

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
settings.json:2
Finding

API Key Transmitted to the Default Analysis Service over Plaintext HTTP

Content
View full analysis
str: return f"{config.WEBAPI_BASE_URL}/{path.lstrip('/')}" def _post(path: str, json_body: dict = None, raw: bool = False) -> Optional[Any]: try: resp = _session.post( _url(path), json=json_body or {}, timeout=config.TIMEOUT ) ``` The complete stored API key is inserted into the request body: ```python body = {"code": code} if config.API_KEY: body["apiKey"] = config.API_KEY if today_kline: body["todayKline"] = today_kline data = _post("klineanalyze", body) ``` ### Technical Analysis HTTP provides no transport encryption or authenticated server identity. As a result, the JSON body containing `apiKey` is exposed in plaintext between the client and the configured API service. Any party able to observe or modify network traffic can read the key, alter the request, or replace the analysis response. Potential interceptors include: - A malicious or compromised Wi-Fi access point. - A local network administrator. - A compromised router. - An upstream proxy or ISP. - Malware with access to local network traffic. - An attacker performing ARP, DNS, or routing manipulation. This behavior directly contradicts the Skill d ...[truncated 1724 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
ghdata/db_manager.py:23
Finding

API Key Disclosed to a Separate Payment Domain Without User-Initiated Purchase Intent

Content
View full analysis
str: now = time.time() if _PAYMENT_CACHE["url"] and now - _PAYMENT_CACHE["ts"] < _PAYMENT_CACHE_TTL: return _PAYMENT_CACHE["url"] if not config.API_KEY: return "https://www.oraskl.com/ghdata-admin" try: resp = requests.post( _GET_TOKEN_URL, json={"apiKey": config.API_KEY}, timeout=min(config.TIMEOUT, 10), ) if resp.status_code == 200: body = resp.json() if body.get("code") == 0: pay_url = (body.get("data") or {}).get("payUrl") if pay_url: _PAYMENT_CACHE["ts"] = now _PAYMENT_CACHE["url"] = pay_url return pay_url ``` The payment request occurs before paid or preview status has been established: ```python def kline_analyze(code: str, today_kline: dict = None) -> dict: body = {"code": code} if config.API_KEY: body["apiKey"] = config.API_KEY if today_kline: body["todayKline"] = today_kline payment_url = get_payment_url() data = _post("klineanalyze", body) ``` `analyzer.analyze()` also requests a payment URL regardless of preview status: ```python try: api = db.kline_analyze(stock_code) preview = isinstance(api, dict) and api.get("preview") is True result["_payment_url"] = db.get_payment_url() except Exception: preview = False ...[truncated 2236 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
ghdata/config.py:85
Finding

Persistent API-Key File Is Created Without Explicit Restrictive Permissions

Content
View full analysis
bool: try: os.makedirs(_GH_DATA_DIR, exist_ok=True) with open(_APIKEY_FILE, "w", encoding="utf-8") as f: f.write(key.strip()) return True except Exception as e: print(f"[config] save API key file failed {_APIKEY_FILE}: {e}") return False ``` The file is automatically created when no existing key is found: ```python def _ensure_api_key() -> str: existing = _read_apikey_file() if existing and len(existing) > 20: return existing new_key = str(uuid.uuid4()).upper() _write_apikey_file(new_key) return new_key ``` No explicit `0700` directory mode, `0600` file mode, permission verification, or atomic secure creation is used. ### Technical Analysis `open(..., "w")` and `os.makedirs(..., exist_ok=True)` rely on the process umask and existing filesystem permissions. On a system with a permissive umask, shared home directory, inherited access-control lists, or a pre-existing attacker-controlled path, the API-key file may be accessible to another local user. Additional concerns include: - Existing files are truncated without checking ownership or type. - Existing symbolic links are followed. - The code does not verify that `~/.ghdata` is owned by the current user. - Existing insecure permissions are not repaired. - The write is not atomic, which can leave partially written credentials after interruption. ### Attack Path 1. The Skill is imported and initializes configuration automatically. 2. No key file exists, so `_ensure_api_key()` generates a new key. 3. `_write_apikey_file()` creates `~/.ghdata/ghdataapikey` using default permissions. 4. On a permissively configured ...[truncated 793 chars]
Remediation
View remediation
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • 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
Findings (57)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This variant goes beyond mere claim inflation by documenting reads and writes to a fixed credential file and auto-generation/persistence of API credentials, while presenting the skill mainly as an analysis tool. Hidden or under-emphasized credential lifecycle behavior can surprise users, create secret sprawl on disk, and expand the attack surface if local files are later exposed or mispermissioned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

This variant goes beyond mere claim inflation by documenting reads and writes to a fixed credential file and auto-generation/persistence of API credentials, while presenting the skill mainly as an analysis tool. Hidden or under-emphasized credential lifecycle behavior can surprise users, create secret sprawl on disk, and expand the attack surface if local files are later exposed or mispermissioned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This variant goes beyond mere claim inflation by documenting reads and writes to a fixed credential file and auto-generation/persistence of API credentials, while presenting the skill mainly as an analysis tool. Hidden or under-emphasized credential lifecycle behavior can surprise users, create secret sprawl on disk, and expand the attack surface if local files are later exposed or mispermissioned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This variant goes beyond mere claim inflation by documenting reads and writes to a fixed credential file and auto-generation/persistence of API credentials, while presenting the skill mainly as an analysis tool. Hidden or under-emphasized credential lifecycle behavior can surprise users, create secret sprawl on disk, and expand the attack surface if local files are later exposed or mispermissioned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

This variant goes beyond mere claim inflation by documenting reads and writes to a fixed credential file and auto-generation/persistence of API credentials, while presenting the skill mainly as an analysis tool. Hidden or under-emphasized credential lifecycle behavior can surprise users, create secret sprawl on disk, and expand the attack surface if local files are later exposed or mispermissioned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

This variant goes beyond mere claim inflation by documenting reads and writes to a fixed credential file and auto-generation/persistence of API credentials, while presenting the skill mainly as an analysis tool. Hidden or under-emphasized credential lifecycle behavior can surprise users, create secret sprawl on disk, and expand the attack surface if local files are later exposed or mispermissioned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

This variant goes beyond mere claim inflation by documenting reads and writes to a fixed credential file and auto-generation/persistence of API credentials, while presenting the skill mainly as an analysis tool. Hidden or under-emphasized credential lifecycle behavior can surprise users, create secret sprawl on disk, and expand the attack surface if local files are later exposed or mispermissioned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This variant goes beyond mere claim inflation by documenting reads and writes to a fixed credential file and auto-generation/persistence of API credentials, while presenting the skill mainly as an analysis tool. Hidden or under-emphasized credential lifecycle behavior can surprise users, create secret sprawl on disk, and expand the attack surface if local files are later exposed or mispermissioned.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill claims it does not generate conclusions, yet later mandates directional judgments, ratings, and conclusion text. This kind of contradictory instruction can mislead reviewers and users about the skill's real function, making risky decision-support behavior appear harmless and reducing informed consent around financially sensitive outputs.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill requests and documents capabilities for network access, local file read/write, and environment-variable access, but it does not declare an explicit tool scope or permissions block. That creates a governance gap: reviewers and runtime policy engines cannot easily constrain or audit what the skill is allowed to touch, increasing the chance of overbroad data access or unintended side effects.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest description is written entirely in Chinese and presents the skill as operating in that language, with no indication that other languages are supported or that the user can choose a locale. Under the policy rule, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is clearly documented and justified.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The manifest frames the skill as analysis/reporting, but the body also embeds conversion-focused payment-link generation and upsell behavior. Undeclared monetization flows can trick users into activating external purchase journeys they did not expect, and in agent ecosystems this can blur the line between analysis and commercial redirection.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Early compliance rules prohibit suggesting the tool recommends stocks, predicts price movement, or advises buy/sell/hold. Later preview templates include lines such as '现在该买还是该卖吗?' and other sales copy framing the hidden content as decision-making guidance. That contradicts the stated output restrictions rather than merely omitting nuance.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This section mandates specific Chinese replacements for output wording and translation rules for API fields, effectively constraining responses to Chinese phrasing. The file does not provide a user-facing option to select another language, so this constitutes a locale/language policy issue rather than a content-safety one.

Content

No source excerpt is available for this finding.

Ssd 4

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The preview flow uses manipulative upsell language to steer users from neutral data viewing toward paid, more persuasive decision guidance. In a financial-analysis context, this increases the risk of coercive or misleading user influence, especially when mixed with claims of signal quality, historical match rates, and actionable guidance framing.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This Python file contains user-facing formatted output and CLI messages entirely in Chinese, including a docstring that says the formatter is for direct LLM output. Because the skill presents fixed-language output without any mechanism to let the user choose locale or opt in, it conflicts with the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The module title and primary user-facing documentation strings are entirely in Chinese, which imposes a specific language on users without any indication of locale choice. Under the stated policy, forcing a language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The analyzer injects a payment/conversion URL into every analysis result, including when the caller only requested stock-analysis output. This creates a covert monetization/data-flow channel in a function that should return analytical data, and the hidden side effect could mislead downstream agents or users into surfacing promotional or tracking links unexpectedly.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Checking payment status and generating payment links inside the core analysis routine mixes unrelated business logic into a data-analysis function. In an agent setting, this can become a deceptive capability escalation: a caller asking for stock insights also triggers monetization behavior and receives payment artifacts that may encode identity or account state.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · ghdata/analyzer.py (reported line 135)May include surrounding context.

python
groups[p['pattern_type']].append(p)

            summary = []
            for idx, (ptype, plist) in enumerate(sorted(groups.items()), 1):
                plist_sorted = sorted(plist, key=lambda x: x['created_at'] or '', reverse=True)
                latest_p = plist_sorted[0]
                verify_count = len(plist_sorted)

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · ghdata/analyzer.py (reported line 136)May include surrounding context.

python
groups[p['pattern_type']].append(p)

            summary = []
            for idx, (ptype, plist) in enumerate(sorted(groups.items()), 1):
                plist_sorted = sorted(plist, key=lambda x: x['created_at'] or '', reverse=True)
                latest_p = plist_sorted[0]
                verify_count = len(plist_sorted)

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · ghdata/analyzer.py (reported line 137)May include surrounding context.

python
groups[p['pattern_type']].append(p)

            summary = []
            for idx, (ptype, plist) in enumerate(sorted(groups.items()), 1):
                plist_sorted = sorted(plist, key=lambda x: x['created_at'] or '', reverse=True)
                latest_p = plist_sorted[0]
                verify_count = len(plist_sorted)

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · ghdata/analyzer.py (reported line 138)May include surrounding context.

python
groups[p['pattern_type']].append(p)

            summary = []
            for idx, (ptype, plist) in enumerate(sorted(groups.items()), 1):
                plist_sorted = sorted(plist, key=lambda x: x['created_at'] or '', reverse=True)
                latest_p = plist_sorted[0]
                verify_count = len(plist_sorted)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The module title, comments, docstrings, and font settings are explicitly tailored to Chinese usage, including SimHei, Microsoft YaHei, and Noto Sans SC. This indicates a Chinese locale assumption in the skill behavior without offering a language choice or documenting that the skill is intentionally region-specific.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module is presented as a chart-rendering utility, but the exported generate() function performs an undisclosed network fetch to Tencent API before rendering. In agent environments, hidden outbound network access can violate least-surprise and data-flow expectations, expanding the trust boundary and creating privacy, compliance, or supply-chain risk if callers assume the function is purely local/offline.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
ghdata/config.py:122