Back to skill

Security audit

Stock AI Analyzer

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent A-share stock analysis skill, but its database, import-path, HTTP download, and HTML rendering choices create security risks that warrant review before installation.

Install only in a contained environment. Configure unique PostgreSQL credentials or use SQLite, do not rely on alpha_user/alpha_pass, restrict the database role to the needed tracking tables, and ensure ancestor shared directories are not writable by untrusted users or skills. Treat downloaded PDFs and generated HTML as untrusted content; prefer strict validation and avoid opening reports in a sensitive browser context.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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
Findings (5)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/_shared/db_core.py:41
Finding

Hardcoded Active PostgreSQL Credentials

Content
View full analysis
Backend: raw = os.getenv("ALPHA_DB_BACKEND", "postgresql").strip().lower() try: return Backend(raw) except ValueError as exc: allowed = ", ".join(backend.value for backend in Backend) raise RuntimeError( f"Invalid ALPHA_DB_BACKEND={raw!r}; expected one of: {allowed}" ) from exc def _read_pg_url() -> str: # ALPHA_PG_URL is the canonical CH Skills variable. DATABASE_URL is accepted # only as a compatibility fallback for generic agent/scheduler runtimes. return ( os.getenv("ALPHA_PG_URL") or os.getenv("DATABASE_URL") or DEFAULT_PG_URL ) ``` The same credential is documented as a usable default and TCP fallback in `scripts/_shared/POSTGRESQL.md:8-17,35`. ### Technical Analysis The PostgreSQL username and password are embedded in executable code. This is not only sample documentation: `_read_pg_url()` actively selects the credential-bearing DSN whenever `ALPHA_PG_URL` and `DATABASE_URL` are absent. A fixed credential distributed with the Skill cannot be treated as secret. Any local user or process that can inspect the package can recover it. If an installation creates the documented account with this password, an attacker may authenticate through the Unix socket. Exposure is greater if the documented TCP fallback is enabled without restrictive listener and firewall settings. Database persistence is legitimate for the declared stock-tracking feature, but a universal default password is not required and violates least-privilege credential management. ### Attack Path 1. An attacker reads the publicly distributed Skill package or docume ...[truncated 955 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/cninfo.py:268
Finding

CNInfo Queries and PDF Downloads Use Cleartext HTTP

Content
View full analysis
Dict[str, str]: """Headers for CNInfo announcement endpoints.""" return { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9", "Connection": "keep-alive", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "Host": "www.cninfo.com.cn", "Origin": "http://www.cninfo.com.cn", "Referer": "http://www.cninfo.com.cn/new/commonUrl/pageOfSearch?url=disclosure/list/search", "User-Agent": ( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" ), "X-Requested-With": "XMLHttpRequest", } def build_cninfo_url(path_or_url: str) -> str: """Normalize a CNInfo announcement path or URL to a full URL.""" raw = str(path_or_url or "").strip() if not raw: raise ValueError("CNInfo report URL cannot be empty.") if raw.startswith("http://") or raw.startswith("https://"): parsed = urlparse(raw) if parsed.hostname not in CNINFO_ALLOWED_HOSTS: raise ValueError(f"Unsupported CNInfo host: {parsed.hostname}") return raw normalized = raw.lstrip("/") return f"http://static.cninfo.com.cn/{normalized}" ``` The core fetcher also directly posts to: ```python "http://www.cninfo.com.cn/new/information/topSearch/query" "http://www.cninfo.com.cn/new/hisAnnouncement/query" ``` ### Technical Analysis CNInfo metadata requests and report downloads are made over unencrypted HTTP. The hostname allowlist reduces arbitrary-host SSRF risk, but it does not provide transport au ...[truncated 1554 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/_shared/html_report/markdown_engine.py:53
Finding

Unsafe Markdown Link Schemes Permit Script Execution

Content
View full analysis
str: escaped = html.escape(text) code_values: List[str] = [] def keep_code(match: re.Match[str]) -> str: code_values.append(f"{match.group(1)}") return f"@@CODE{len(code_values) - 1}@@" escaped = re.sub(r"`([^`]+)`", keep_code, escaped) escaped = re.sub(r"==([^=\n]+)==", r"\1", escaped) escaped = re.sub(r"\*\*([^*]+)\*\*", r"\1", escaped) escaped = re.sub(r"(?\1", escaped) escaped = re.sub(r"\[([^\]]+)\]\(([^)]+)\)", r'\1', escaped) for idx, value in enumerate(code_values): escaped = escaped.replace(f"@@CODE{idx}@@", value) return escaped ``` ### Technical Analysis The renderer HTML-escapes Markdown text but inserts link destinations into `href` without validating their URL schemes. HTML escaping prevents ordinary attribute termination, but it does not make active schemes such as `javascript:` safe. For example: ```markdown [Open source](javascript:alert(document.domain)) ``` is rendered as: ```html Open source ``` When clicked in a browser, the URL executes JavaScript in the generated report’s document context. Reports are designed to include links copied from announcements and online research, so a hostile or mistakenly propagated URL can reach this sink. ### Attack Path 1. An attacker causes a malicious link to appear in Markdown supplied to the renderer, or a report author copies an untrusted URL into the report. 2. `inline_markdown()` converts the Markdown link into an unrestricted anchor. 3. The generated HTML is opened in a browser. 4. The victim clicks the apparently legitima ...[truncated 512 chars]
Remediation
View remediation

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/tracking_store.py:25
Finding

Ancestor Directory Can Shadow the Bundled Database Module

Content
View full analysis
Remediation
View remediation

other

Note
Location
scripts/_shared/html_report/builder.py:34
Finding

Generated Reports Contact Google Font Services by Default

Content
View full analysis
\n' ' \n' ' ' ) ``` ```python class HtmlReportBuilder: def __init__( self, title: str, theme: str = "default", meta_text: str = "", extra_css: str = "", extra_head: str = "", lang: str = "zh-CN", font_links: bool = True, ) -> None: self.title = title self.theme = theme self.meta_text = meta_text self.extra_css = extra_css self.extra_head = extra_head self.lang = lang self.font_links = font_links ``` ```python font_block = _FONT_LINKS if self.font_links else "" ``` The normal renderer constructs `HtmlReportBuilder` without overriding `font_links`, so the default remains enabled. ### Technical Analysis Generated reports are described as self-contained, but the default HTML includes preconnection and stylesheet requests to Google-controlled domains. When a report is opened online, the browser contacts those services. The requests disclose network and browser metadata, including the viewer’s IP address, access time, user-agent characteristics, and potentially referrer information depending on browser and hosting behavior. This behavior is unnecessary for the report-rendering function because fonts can be bundled or system fonts can be used. ### Attack Path 1. A report is rendered with default settings. 2. The resulting HTML contains Google Fonts resource links. 3. A use ...[truncated 482 chars]
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • 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 (54)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description centers on stock fundamental analysis workflows and permitted supporting scripts for data retrieval and deterministic scanning related to that investment-research use case. The actual code does not analyze stocks, retrieve market data for research output, render HTML, or persist analysis state. Instead, its primary purpose is infrastructure diagnostics: checking database connectivity and verifying schema/table presence. While such a utility could be a supporting internal tool, the evaluation criteria say to flag mismatches when code has a materially different primary purpose or inconsistent resource access. Here the code operates on generic shared database health rather than implementing the described A-share analysis behavior, so the description does not accurately represent this specific code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose centers on stock fundamental analysis workflows and constraints around how scripts may support that process. The actual code chunk does not perform data retrieval, financial analysis, valuation assessment, governance review, or any stock-related logic. Instead, it simply reads a bundled JavaScript asset used for charts/UI rendering. While HTML rendering support is mentioned as an allowed script function, this specific code’s primary purpose is a generic shared frontend asset loader, which is materially different from the declared end-user skill description and contains no visible stock-analysis behavior. Therefore, for this code chunk alone, the description does not accurately represent what it actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is about stock fundamental analysis methodology and related investment-research use cases for Chinese A-shares. However, the provided code does not perform any stock analysis, data retrieval, financial evaluation, valuation work, governance assessment, or deep research. Instead, it is a generic shared reporting utility whose purpose is to render Markdown into HTML and manage CLI behavior around that rendering. While the broader description allows scripts to do read-only HTML rendering, this specific code chunk’s actual purpose is only report-rendering infrastructure and not the claimed analysis functionality. Therefore, this code chunk does not accurately represent the declared skill behavior and is materially mismatched in primary purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared purpose is a stock fundamental research skill focused on A-share company analysis and explicitly says scripts should not generate investment conclusions and are limited to data fetching, deterministic scanning, persistence, and read-only HTML rendering. This code does not perform any stock analysis, data retrieval, Tushare access, financial evaluation, risk analysis, or market-mainline judgment. Instead, it is a shared front-end/report-rendering utility that injects JavaScript and CSS to restructure DOM content and add interactivity (collapsible update cards, hero summaries, clickable version timelines, pill styling). While report rendering support could be adjacent infrastructure, this specific code is a generic UI-decoration module whose primary purpose is materially different from the declared stock-analysis skill behavior. Therefore this is a clear description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This code chunk is unrelated to A-share stock fundamental analysis. It does not fetch market data, analyze companies, evaluate valuation, assess financials, or generate investment-research content. Instead, it performs a deterministic utility function: validating that rendered HTML preserves visible text from Markdown. While the declared description allows scripts for atomic data retrieval, deterministic scanning, state persistence, and read-only HTML rendering, this validator is specifically a rendering QA helper and not part of the described stock-analysis behavior. Its primary purpose is materially different from the declared skill purpose, so this is a clear mismatch.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 14)May include surrounding context.

md
- 所有内容逻辑都放在本 `SKILL.md` 中:分析路径、判断标准、报告结构、措辞边界。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 204)May include surrounding context.

md
- 所有内容逻辑都放在本 `SKILL.md` 中:分析路径、判断标准、报告结构、措辞边界。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 15)May include surrounding context.

md
s/thesis_scan.py`;持续跟踪状态写入用 `scripts/tracking_table.py`;Markdown 到 HTML 的只读渲染用 `scripts/render_report_html.py`。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 92)May include surrounding context.

md
s/thesis_scan.py`;持续跟踪状态写入用 `scripts/tracking_table.py`;Markdown 到 HTML 的只读渲染用 `scripts/render_report_html.py`。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 95)May include surrounding context.

md
s/thesis_scan.py`;持续跟踪状态写入用 `scripts/tracking_table.py`;Markdown 到 HTML 的只读渲染用 `scripts/render_report_html.py`。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 158)May include surrounding context.

md
s/thesis_scan.py`;持续跟踪状态写入用 `scripts/tracking_table.py`;Markdown 到 HTML 的只读渲染用 `scripts/render_report_html.py`。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 238)May include surrounding context.

md
s/thesis_scan.py`;持续跟踪状态写入用 `scripts/tracking_table.py`;Markdown 到 HTML 的只读渲染用 `scripts/render_report_html.py`。

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
86% confidence
Finding

The documented --no-validate option allows complete skipping of text-preservation validation during HTML rendering. In a workflow that transforms untrusted or semi-trusted report content, making validation optional—and describing failure as a silent downgrade—can let malformed or manipulated output pass unnoticed, weakening integrity safeguards.

Content

Scanner excerpt · SKILL.md (reported line 106)May include surrounding context.

md
- 图表锚点是"尽力而为"。找不到对应小标题(如「估值方法与相对贵贱」「成长性与财务质量诊断」「核心判断」)时,对应图表**静默跳过**,不报错。
- evidence 缺某个数据集时,对应图表自动不画,正文照常输出。
- 文本保全校验默认**只告警不中断**(`--no-validate` 完全跳过,`--strict` 才在不一致时报错),正文内容怎么改都不会导致 HTML 生成失败。
- 沿用模板(第八节)里的小标题命名能让图表落到最合适的位置;即使大改结构,最坏情况也只是少几张图,正文与样式不受影响。
- 正文明确作废自身历史估值带(如"历史分位:不适用/已作废",典型于破产重整壳)时,估值带图**自动不画**,避免把作废口径画回报告。

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/_shared/html_report/README.md (reported line 41)May include surrounding context.

md
"""Shared CLI for ``render_report_html.py`` entrypoints.

Every skill renderer did the same dance: parse ``--input/--output/--title/
--theme/--no-validate``, read the Markdown, build an ``HtmlReportBuilder``,
render with a "warn-don't-fail" validation policy, write the file, print a
JSON summary. That orchestration lives here once. A skill supplies only the
variable part — a ``build_job(args) -> RenderJob`` that loads its evidence,

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/_shared/html_report/cli.py (reported line 4)May include surrounding context.

python
"""Shared CLI for ``render_report_html.py`` entrypoints.

Every skill renderer did the same dance: parse ``--input/--output/--title/
--theme/--no-validate``, read the Markdown, build an ``HtmlReportBuilder``,
render with a "warn-don't-fail" validation policy, write the file, print a
JSON summary. That orchestration lives here once. A skill supplies only the
variable part — a ``build_job(args) -> RenderJob`` that loads its evidence,

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/_shared/html_report/cli.py (reported line 86)May include surrounding context.

python
"""Shared CLI for ``render_report_html.py`` entrypoints.

Every skill renderer did the same dance: parse ``--input/--output/--title/
--theme/--no-validate``, read the Markdown, build an ``HtmlReportBuilder``,
render with a "warn-don't-fail" validation policy, write the file, print a
JSON summary. That orchestration lives here once. A skill supplies only the
variable part — a ``build_job(args) -> RenderJob`` that loads its evidence,

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/tushare_client.py (reported line 22)May include surrounding context.

python
if token:
        return token

    env_path = os.path.join(os.getcwd(), ".env")
    if not os.path.exists(env_path):
        return ""

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill advertises substantial capabilities—environment variable use, file read/write, and network access—but does not declare an explicit tool scope or allowlist. That makes the effective privilege boundary unclear and increases the chance an agent invokes more capability than the user or platform expects.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest description is entirely framed around Chinese A-share analysis and the skill title/content instruct the agent in Chinese, while the style guidance later reinforces a fixed Chinese writing style. There is no indication that users may choose another language or that the Chinese-only constraint is optional, which can violate language/locale choice policy.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The entire skill methodology, required protocol strings, and report templates are specified only in Chinese, including mandatory user-facing outputs like [Deep 模式启动] and [Deep 模式完成]. There is no indication that the user may choose another language or locale, so the skill effectively enforces a specific language without opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The entire skill file is written in Chinese and provides no indication that users may choose another language or locale. Per the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is explicitly justified, which is not present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The document title and all instructional content are written in Chinese, and there is no natural-language statement indicating that users may choose another language or locale. Under the policy rule, a skill that effectively requires a specific language without opt-in is a locale-policy concern unless the constraint is explicitly justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The entire skill file is written in Chinese and repeatedly specifies agent-facing operational protocol in Chinese, with no indication that users may choose another language or that the skill is intended only for a Chinese-specific compliance or regional context. Under the policy, forcing a specific language without opt-in is a natural-language locale violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The title and the entire document are written in Chinese, and there is no natural-language indication that users may choose another language or that the skill is intentionally limited to a Chinese-speaking or region-specific context. Under the stated policy, forcing a specific language without opt-in is a locale-policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

标题和全文说明均以中文呈现,未见提供用户语言/locale 选择,也未说明这是仅面向特定中文环境的区域性文档。根据规则,强制特定语言而无用户 opt-in 属于自然语言政策风险。

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.