Back to skill

Security audit

上市公司年报/研报抓取

Security checks for vulnerabilities and agentic risk

Overview

The skill is mainly a financial-report downloader, but it has unsafe download/session-handling patterns that users should review before installing.

Install only in an isolated virtual environment or container, run as a non-privileged user, keep outputs in a dedicated directory, avoid authenticated Hibor/login workflows unless you secure session files yourself, and treat downloaded PDFs as untrusted until the downloader validates HTTPS, paths, content type, size, and PDF signatures.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/financial_report_fetcher.py:32
Finding

Financial report metadata and documents are retrieved over plaintext HTTP

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/financial_report_fetcher.py:137
Finding

Remote announcement fields can escape the download directory and unvalidated content is parsed as PDF

Content
View full analysis
|]', "", title) safe_name = re.sub(r'[\\/*?:"<>|]', "", sec_name) filename = f"{sec_code}_{safe_name}_{safe_title}.pdf" # Create directory by company code company_dir = os.path.join(output_dir, sec_code) os.makedirs(company_dir, exist_ok=True) filepath = os.path.join(company_dir, filename) if dry_run: print(f"[DRY RUN] Will download: {filename}") print(f" URL: {pdf_url}") return filepath try: headers = get_headers("http://www.cninfo.com.cn/new/disclosure") resp = requests.get(pdf_url, headers=headers, timeout=30, stream=True) resp.raise_for_status() with open(filepath, "wb") as f: for chunk in resp.iter_content(chunk_size=8192): f.write(chunk) ``` `secCode` and `adjunctUrl` originate in the remote announcement response. Although the title and company name undergo limited filename-character removal, `secCode` is not validated or sanitized. The optional parsing flow later processes the resulting file based solely on its path: ```python if parse_pdf and not dry_run and os.path.exists(filepath): print(f"\n--- Parse PDF: {os.path.basename(filepath)} ---") parse_pdf_financial_data(filepath) ``` ### Technical Analysis The code incorporates remote-controlled `secCode` directly into both a directory path and filename. Values containing absolute paths, `..`, or path separators can cause `os.path.join` to resolve outside the intended download director ...[truncated 1983 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:454
Finding

Setup instructions install unpinned third-party packages and browser binaries

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:314
Finding

Documented browser login workflow stores bearer session state in a predictable plaintext file

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (13)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

总体领域相近,都是金融报告抓取,但声明明显高于代码实际能力。代码的核心功能是从巨潮资讯抓取公告 PDF,并可解析已下载 PDF,确实符合“上市公司年报抓取”的一部分;但它没有实现东方财富等其他数据源,也没有按公司名称或行业检索/批量处理的能力。CLI 中虽有 --research 和 --months 参数,但主流程完全未使用这些参数来实现研报抓取,因此“研报自动抓取”与实际不符。另外,所谓“内置反爬绕过”在代码中仅体现为随机 User-Agent、Referer 和延时,这更像基础伪装而非明确的绕过能力。基于这些重要功能差异,应判定描述与实际行为存在不匹配。

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill describes network access, file reads/writes, and local storage of downloaded PDFs/metadata, but it does not declare an explicit tool scope or permission boundary. In an agent setting, missing scope declarations increase the chance of unintended capability use and make it harder for operators or users to understand what the skill can access.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill includes login simulation and credential-handling instructions for third-party sites, even though much of its stated purpose involves public filings that do not require authentication. This expands the attack surface to credential theft, insecure secret storage, and session persistence misuse, especially where storage_state files are written locally.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The skill encourages login simulation, cookie persistence, and bulk local downloads without prominent warnings about how credentials, cookies, and downloaded files will be stored and protected. In an agent environment, this can lead to accidental retention of sensitive session tokens or storage of large third-party data sets in unsafe locations.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
- **PDF 直链**: `https://pdf.dfcfw.com/pdf/H3_{infoCode}_1.pdf`
  - 无需登录,直接 GET 即可下载
  - 需检查 content-type 是否为 `application/pdf`,防止 404 返回 HTML
- **详情页**: `https://data.eastmoney.com/report/info/{infoCode}.html`
- **反爬**: 列表 API 无需登录、无反爬;PDF 直链也无需登录。页面抓取需 Playwright(JS 渲染)

### 行业代码参考

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
- **PDF 直链**: `https://pdf.dfcfw.com/pdf/H3_{infoCode}_1.pdf`
  - 无需登录,直接 GET 即可下载
  - 需检查 content-type 是否为 `application/pdf`,防止 404 返回 HTML
- **详情页**: `https://data.eastmoney.com/report/info/{infoCode}.html`
- **反爬**: 列表 API 无需登录、无反爬;PDF 直链也无需登录。页面抓取需 Playwright(JS 渲染)

### 行业代码参考

External Transmission

Medium
Category
Data Exfiltration
Confidence
72% confidence
Finding

This section combines third-party page fetching with stealth/scraping automation intended to bypass anti-bot controls. In context, that is more risky than ordinary outbound access because it may trigger access-control circumvention behavior and increases exposure to untrusted remote content through a browser-like fetch path.

Content

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

md
# 方式2:Scrapling stealth 模式(需要登录/有反爬时)
from scrapling.fetchers import StealthyFetcher
page = StealthyFetcher.fetch(
    "https://data.eastmoney.com/report/{stock_code}.html",
    headless=True,
    solve_cloudflare=False,
    timeout=30

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest describes a skill for automatically fetching listed-company annual reports and research reports by company code/name/year/industry, implying company-targeted financial-report retrieval. This file contains many generic industry, macro, hotel/catering, tourism, and consumer-service reports with empty stockName/stockCode fields, indicating the skill is collecting broad sector research rather than company-specific listed-company reports.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring includes an example using '--research', and the CLI defines '--research' as '研报模式(预留)'. However, the flag is never used in control flow, and the fetching logic always performs the same 巨潮公告/报告 search path. This documentation suggests a capability that the code does not actually provide.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest describes a broader fetcher covering multiple sources, company code/name/year/industry batch download, and annual reports/research reports. In this file, the implemented retrieval logic is hard-coded to 巨潮资讯 endpoints and the CLI only accepts stock codes and years; there is no implementation for company-name lookup, industry-based retrieval, 东方财富 access, or research-report fetching.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The Accept-Language header is fixed to "zh-CN,zh;q=0.9,en;q=0.8", which imposes a specific locale preference for all requests. The file does not offer the user any language/locale opt-in or explain why this restriction is required, so it matches the language/locale policy violation category.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest description and the rest of the skill instructions are presented entirely in Chinese, which effectively imposes a language constraint without any user opt-in or stated locale-specific justification. The policy requires flagging language or locale restrictions unless the skill offers a choice or clearly documents why the constraint is necessary.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

This JSON file is primarily Chinese-language content, but the rating field at L1698 uses a mixed-language label "看好(Overweight)". Under the natural-language policy rule, forcing or introducing a specific language/locale convention without any visible opt-in or justification can be a locale consistency issue.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.