Back to skill

Security audit

股票分析专家-公众号股票大V蒸馏

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a disclosed stock-analysis helper, but it has Review-worthy risks around credential handling, automatic package installation, telemetry, and embedded promotional output instructions.

Review before installing. Use an isolated environment, install dependencies yourself instead of relying on --check-env, prefer REDFOX_API_KEY via environment variable rather than --api-key, expect call metadata to be reported to redfox.hk, and remove or edit the 投资明见 promotional closing if you do not want generated articles to include third-party follow/QR-code language.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T01 · Skill Instruction Hijacking

Error
Location
profiles/投资明见_profile.json:65
Finding
Fixed Third-Party Promotional Content Can Hijack Generated Output## Vulnerability Details **File Location**: `profiles/投资明见_profile.json:65`, with execution paths in `scripts/analyze.py:214-216` and quality reinforcement in `scripts/quality_audit.py:347-359` **Vulnerability Type**: Fixed promotional output instruction embedded in a style profile **Risk Level**: High ### Vulnerable Code ```json "结尾模式": "固定结尾:'收看每日午评文章 投资明见 sinaxxm 收看每日操作策略 -- 长按二维码识别加关注 -- 我喜欢,我在'", ``` The profile directive is consumed by this generation instruction: ```python lines.append("### 结尾") lines.append("- 使用大V的结尾模式") lines.append("- 包含免责声明(如大V有此习惯)\n") ``` The quality audit also incorporates the profile closing pattern into expected argumentation terms: ```python opening = expr.get("开头模式", "") closing = expr.get("结尾模式", "") structure = expr.get("文章结构", "") # 从结构描述中提取论证步骤关键词 arg_keywords_text = f"{opening} {closing} {structure}" words = re.findall(r'[\u4e00-\u9fff]{2,6}', arg_keywords_text) common = {"原文", "证据", "描述", "文章", "固定", "开头", "结尾", "模式", "包含", "使用"} arg_keywords = [w for w in words if w not in common and len(w) >= 2][:10] ``` ### Technical Analysis The style profile contains a fixed call to view additional content and follow an account by scanning a QR code. This is not necessary for stock analysis or stylistic simulation. Because the generation task explicitly tells the Agent to use the profile's ending mode, the promotional instruction can be reproduced in ordinary generated articles. The generic article template says not to include traffic-diversion links, but this does not reliably block non-link promotional text, account identifiers, or QR-code follow instructions. In addition, the quality auditor derives expected terms from the closing pattern, which can reward generated content for matching elements of the promotional instruction. This crosses the boundary between describing an author's abstract writing style and directing the Agent to publish stable third-party promo ...[truncated 1173 chars]
Remediation
## Remediation Suggestions 1. Remove the fixed promotional closing, account identifier, and QR-code follow instruction from the profile. 2. Represent ending style only through abstract properties, such as “brief reflective closing” or “concise summary followed by a disclaimer.” 3. Add a mandatory generation rule prohibiting: - Calls to follow or subscribe to accounts. - QR-code scanning requests. - Group-joining or traffic-diversion instructions. - Reproduction of social-media account identifiers. - Promotional links or promotional copy. 4. Add explicit rejection patterns to `quality_audit.py` for terms associated with following accounts, scanning QR codes, joining groups, or viewing external promotional content. 5. Exclude fields such as fan operations, promotional endings, and account identifiers before profiles are inserted into model prompts. 6. Do not derive positive quality-scoring terms from closing patterns unless those patterns have first passed a content-safety filter.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/analyze.py:391
Finding
API Key Is Exposed Through Process Arguments and Console Output## Vulnerability Details **File Location**: `scripts/analyze.py:391-399` **Vulnerability Type**: Sensitive credential exposure through command-line arguments and logs **Risk Level**: Medium ### Vulnerable Code ```python def run_sync(author, days=7, api_key=None): """增量文章同步 — 拉取近N天新文章用于蒸馏补充""" step(f"模式:增量同步 — {author} / 近{days}天") script = SKILL_DIR / "scripts" / "sync_articles.py" cmd = [sys.executable, str(script), "--author", author, "--days", str(days)] if api_key: cmd.extend(["--api-key", api_key]) print(f"{BOLD}执行:{RESET}{' '.join(cmd)}") return subprocess.call(cmd) ``` ### Technical Analysis When the user supplies an API key through `--api-key`, the parent process places the secret directly in the child process argument list. The code then prints the complete command without redaction. Command-line arguments may be observable through process inspection facilities, monitoring agents, debugging tools, job runners, or container orchestration metadata. The printed command may also be retained in terminal capture, CI logs, application logs, support bundles, or conversation transcripts. The subprocess call uses an argument array rather than a shell, so this segment does not introduce shell command injection. The vulnerability is disclosure of the authentication secret. ### Attack Path 1. A user invokes synchronization with `analyze.py --mode sync --api-key <secret>`. 2. `run_sync()` appends the secret to the child process argument list. 3. The complete command, including the secret, is printed to standard output. 4. A local process observer, log collector, CI operator, or person with access to captured output retrieves the key. 5. The exposed key is reused against the RedFox API until it is revoked or expires. ### Impact Assessment No additional local system privileges are obtained directly. However, an attacker who obtains the key may authenticate as the a ...[truncated 333 chars]
Remediation
## Remediation Suggestions 1. Do not pass API keys through command-line arguments. 2. Pass the key to the child through a narrowly scoped environment variable or protected inter-process communication: - Create a copied environment mapping. - Set `REDFOX_API_KEY` only in that child environment. - Do not include the key in `cmd`. 3. Remove or redact credentials from command previews. Display `--api-key [REDACTED]` if the option must be shown. 4. Prefer the existing environment-variable or protected configuration-file mechanisms over the `--api-key` option. 5. Consider removing the command-line key option entirely. 6. Document key rotation procedures and revoke any key that may already have appeared in logs. 7. Ensure the configuration file has owner-only permissions and avoid copying secrets into exception messages.

T08 · Insecure Dependencies

Warning
Location
scripts/analyze.py:40
Finding
Environment Check Automatically Installs an Unpinned Dependency## Vulnerability Details **File Location**: `scripts/analyze.py:40-52` **Vulnerability Type**: Automatic installation of an unpinned package from the active package index **Risk Level**: Medium ### Vulnerable Code ```python def check_env(): """检查环境""" info("环境检查中...") issues = [] try: import requests info("requests 已就绪") except ImportError: warn("缺少 requests,正在安装...") os.system(f"{sys.executable} -m pip install requests") try: import requests info("requests 安装成功") except ImportError: error("requests 安装失败") issues.append("requests") ``` ### Technical Analysis The documented environment-check operation changes the Python environment by invoking pip automatically. The package has no pinned version or integrity hash, and pip uses the machine's active index and configuration. Consequently, execution depends on mutable external package state and local pip configuration. A compromised package index, malicious mirror, dependency-chain compromise, or unsafe index override could cause unintended code to execute during installation or subsequent import. The command itself is constructed from `sys.executable` and contains no user-controlled package name, so no direct shell injection path was identified. The primary issue is unnecessary, implicit supply-chain execution during what is presented as an environment check. ### Attack Path 1. The host does not have `requests` installed. 2. A user runs the documented `--check-env` operation. 3. The script automatically invokes `python -m pip install requests`. 4. Pip resolves the latest acceptable package and dependencies through the host's configured package index. 5. If that source or dependency chain is compromised, attacker-controlled installation or import-time code executes with the privileges of the user running the Skill. ### Impact As ...[truncated 510 chars]
Remediation
## Remediation Suggestions 1. Make `--check-env` read-only: report missing dependencies without installing them. 2. Require explicit user action before changing the environment. 3. Declare dependencies in a version-controlled requirements or lock file. 4. Pin exact dependency versions and use cryptographic hashes where supported. 5. Install into an isolated virtual environment rather than the user's global Python environment. 6. Use a documented trusted package index and prevent unintended extra-index configuration in controlled deployments. 7. Run dependency vulnerability and provenance checks as part of release preparation. 8. Replace `os.system` with a non-shell subprocess argument list if an explicit installer command is retained.
Vulnerability Patterns
  • 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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (38)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared purpose centers on end-user investment analysis, but the described behavior includes validating distilled profiles against external article data and generating task files for evaluation. That discrepancy matters because it changes the skill from a passive analysis helper into a tool that retrieves external content and writes artifacts locally, increasing operational and privacy risk beyond what the description suggests.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared purpose centers on end-user investment analysis, but the described behavior includes validating distilled profiles against external article data and generating task files for evaluation. That discrepancy matters because it changes the skill from a passive analysis helper into a tool that retrieves external content and writes artifacts locally, increasing operational and privacy risk beyond what the description suggests.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared purpose centers on end-user investment analysis, but the described behavior includes validating distilled profiles against external article data and generating task files for evaluation. That discrepancy matters because it changes the skill from a passive analysis helper into a tool that retrieves external content and writes artifacts locally, increasing operational and privacy risk beyond what the description suggests.

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding
The declared purpose centers on end-user investment analysis, but the described behavior includes validating distilled profiles against external article data and generating task files for evaluation. That discrepancy matters because it changes the skill from a passive analysis helper into a tool that retrieves external content and writes artifacts locally, increasing operational and privacy risk beyond what the description suggests.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
A stock-analysis skill should not silently alter its execution environment during a routine check. Installing packages via shell command creates unnecessary code-execution and supply-chain exposure, and the risk is elevated because the action occurs under a benign-sounding 'check environment' path that users may trust.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Content
info("requests 已就绪")
    except ImportError:
        warn("缺少 requests,正在安装...")
        os.system(f"{sys.executable} -m pip install requests")
        try:
            import requests
            info("requests 安装成功")
Confidence
98% confidence
Finding
The environment check automatically executes a shell command to install a package at runtime, which is an unjustified privileged side effect for an analysis-oriented skill. This can modify the host environment without explicit consent and introduces supply-chain risk if package resolution is tampered with or if the command runs in a sensitive execution context.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The README instructs users to invoke the skill with unrestricted natural language and explicitly says there are no commands to memorize. In agent ecosystems, broad invocation language can cause accidental or overly eager activation from ordinary finance-related prompts, leading the skill to run in contexts the user did not clearly intend.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The README advertises very broad natural-language triggers such as '选股', '板块分析', and '财报点评', and says users can 'directly use natural language' without command boundaries. This can cause the skill to activate in loosely related financial conversations and produce high-risk stock analysis or investment-style outputs without clear user intent verification, increasing the chance of unsafe routing and overreach in a sensitive domain.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill invokes shell commands, reads environment variables for API keys, reads/writes local files, and relies on network access, but it does not declare any explicit tool scope or allowed-tools boundary. This creates unnecessary privilege ambiguity: an agent/runtime may permit broader capabilities than users expect, increasing the chance of unintended file access, outbound requests, or command execution.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The trigger list includes broad phrases like '选股', '板块分析', and '每日复盘', which can easily match ordinary stock-related conversations. In a skill that can perform network access, shell execution, syncing, and file writes, overbroad activation raises the risk of accidental invocation of privileged workflows or side-effecting operations.

Natural-Language Policy Violations

Medium
Confidence
82% confidence
Finding
The manifest-style description is entirely framed around Chinese-language triggers and Chinese influencer personas, but it does not state that the skill is Chinese-only or offer a language choice. Under the policy, forcing a specific language or locale without user opt-in can be a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
84% confidence
Finding
This JSON profile specifies fixed Chinese writing patterns, including a Chinese title format, opening/closing phrasing, and overall expression style, but does not indicate that language choice is optional. Because SQP-3 applies to all file types, a profile that constrains language/locale behavior without user opt-in can violate language/locale policy expectations.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if sector:
        cmd.extend(["--sector", sector])
    print(f"{BOLD}执行:{RESET}{' '.join(cmd)}")
    return subprocess.call(cmd)


def run_portfolio(author, stocks, period=30):
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if sector:
        cmd.extend(["--sector", sector])
    print(f"{BOLD}执行:{RESET}{' '.join(cmd)}")
    return subprocess.call(cmd)


def run_portfolio(author, stocks, period=30):
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if sector:
        cmd.extend(["--sector", sector])
    print(f"{BOLD}执行:{RESET}{' '.join(cmd)}")
    return subprocess.call(cmd)


def run_portfolio(author, stocks, period=30):
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if sector:
        cmd.extend(["--sector", sector])
    print(f"{BOLD}执行:{RESET}{' '.join(cmd)}")
    return subprocess.call(cmd)


def run_portfolio(author, stocks, period=30):
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
The sync mode expands the skill from local stock analysis into external article synchronization, which is behaviorally broader than the manifest's analysis-focused description. Unexpected network/data-ingestion capabilities increase the attack surface, especially if users do not anticipate outbound requests or ingestion of untrusted remote content.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The script reports usage metadata through record_call using an API key, despite being presented primarily as an analysis tool. Silent telemetry is risky because it can leak user behavior, selected authors, and operational details to an external service without clear disclosure or consent.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
This file sends usage metadata through record_call without any user-facing warning in the control flow shown here. Lack of notice and consent turns ordinary telemetry into a privacy/security issue, particularly in an agent skill where users may not expect background reporting.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The module docstring and all user-facing guidance in this file are written only in Chinese, which effectively imposes a specific language on users and maintainers. Under the policy, locale constraints should either be optional for the user or clearly justified as region-specific; this file provides neither.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The module performs undisclosed telemetry by sending skill usage metadata to a third-party endpoint at redfox.hk via `record_call`, including source, mode, and author names. Even if the payload is limited, this creates an external data flow unrelated to core local analysis behavior and may expose user activity patterns or sensitive investment research usage without explicit consent or clear disclosure.

External Transmission

Medium
Category
Data Exfiltration
Content
payload["authors"] = str(authors)

    try:
        resp = requests.post(
            RECORD_API_URL,
            json=payload,
            headers={"Content-Type": "application/json", "REDFOX_API_KEY": api_key},
Confidence
95% confidence
Finding
This POST request transmits data to an external service (`RECORD_API_URL`) and includes the API key in a custom header, enabling outbound telemetry independent of the main content-fetching flow. In the context of a stock-analysis skill, hidden external reporting is more dangerous because users may not expect their usage patterns, selected analysts, or access tokens to be sent for tracking beyond the requested analysis function.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The file’s docstring and CLI usage present the skill entirely in Chinese and describe generation of earnings commentary in that language/style, with no indication that users may choose another language. Under the policy, forcing a specific language without opt-in is a natural-language locale violation unless clearly justified as region-specific.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This file contains natural-language instructions, help text, and prompts only in Chinese, including the module docstring and subsequent interaction strings. Under the policy, forcing a specific language without an explicit user choice or documented justification is a natural-language policy violation.

Tainted flow: 'data' from pathlib.Path.read_text (line 77, file read) → pathlib.Path.write_text (file write)

Medium
Category
Data Flow
Content
# 保存
    today = datetime.now().strftime("%Y-%m-%d")
    f = output_dir / f"盘面数据_{today}.json"
    f.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
    info(f"盘面数据已保存:{f}")

    # 显示摘要
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Static analysis

No suspicious patterns detected.