Back to skill

Security audit

FN Portrait Toolkit

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed Chinese annual-report analysis pipeline, but users should understand its remote LLM use, unpinned dependencies, and insecure HTTP report downloads before installing.

Install this in an isolated Python environment, prefer local Ollama or knowingly opt into DeepSeek/Moonshot, and avoid exposing unrelated API keys. Treat downloaded PDFs as untrusted because CNINFO downloads use HTTP, and consider pinning dependencies before production use.

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 (2)

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned Third-Party Dependencies Create Supply-Chain Risk

Content
View full analysis
Remediation
View remediation
openpyxl== requests== matplotlib== numpy== pillow== pdfplumber== filelock== ``` 2. Generate and commit a lock file that includes resolved transitive dependencies. 3. Record cryptographic hashes and enforce them during installation, such as with pip's `--require-hashes`. 4. Update `SKILL.md` so that installation uses the reviewed requirements or lock file instead of an unconstrained package list. 5. Run dependency vulnerability and license scans in CI. 6. Use an automated update process that opens reviewed pull requests rather than silently selecting new releases at installation time. 7. Install and run the Skill in an isolated virtual environment under a non-privileged user. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ReportLinkCrawler2.py:101
Finding

Annual-Report Search Results and PDFs Are Retrieved over Plaintext HTTP

Content
View full analysis
None: self.config = config self.session = requests.Session() self.session.headers.update(self.HEADERS) self.report_cfg = REPORT_CONFIG[config.report_type] def search_announcements( self, start_date: str, end_date: str ) -> List[Dict[str, Any]]: date_range = f"{start_date}~{end_date}" all_results = [] page_num = 1 while True: data = { "pageNum": page_num, "pageSize": 30, "column": "sse", "tabName": "fulltext", "plate": self.config.plate, "searchkey": "", "secid": "", "category": self.report_cfg['category'], "trade": "", "seDate": date_range, "sortName": "time", "sortType": "desc", "isHLtitle": "false" ...[truncated 5341 chars]
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (49)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

A skill framed as financial footnote extraction but actually centered on whole-report portrait generation and LLM semantic analysis can cause unanticipated data exposure and overbroad execution. In this context, the danger is amplified because annual reports may contain substantial business narrative data that could be transmitted to external LLM providers if the user assumes only structured footnote handling occurs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

A skill framed as financial footnote extraction but actually centered on whole-report portrait generation and LLM semantic analysis can cause unanticipated data exposure and overbroad execution. In this context, the danger is amplified because annual reports may contain substantial business narrative data that could be transmitted to external LLM providers if the user assumes only structured footnote handling occurs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

A skill framed as financial footnote extraction but actually centered on whole-report portrait generation and LLM semantic analysis can cause unanticipated data exposure and overbroad execution. In this context, the danger is amplified because annual reports may contain substantial business narrative data that could be transmitted to external LLM providers if the user assumes only structured footnote handling occurs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

A skill framed as financial footnote extraction but actually centered on whole-report portrait generation and LLM semantic analysis can cause unanticipated data exposure and overbroad execution. In this context, the danger is amplified because annual reports may contain substantial business narrative data that could be transmitted to external LLM providers if the user assumes only structured footnote handling occurs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

A skill framed as financial footnote extraction but actually centered on whole-report portrait generation and LLM semantic analysis can cause unanticipated data exposure and overbroad execution. In this context, the danger is amplified because annual reports may contain substantial business narrative data that could be transmitted to external LLM providers if the user assumes only structured footnote handling occurs.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill declares no explicit tool scope even though the documentation indicates access to environment variables, local file reads/writes, and network-capable workflows. Missing permission boundaries increases the chance an agent invokes the skill with broader privileges than users expect, especially because it handles API keys, downloads files, and writes outputs to disk.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest centers this skill on financial report footnote extraction, annual-report downloading, and financial-data visualization. However, the code also indexes non-footnote sections under '管理层讨论与分析' and later visualizes '核心竞争力' and '经营战略' summaries, which expands the behavior into broader business/strategy analysis rather than just financial footnotes.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

When saving charts, the script conditionally instantiates an external LLM provider and sends portrait data for new trend analysis, which exceeds the described extraction/visualization role. This creates an unannounced outbound data flow and materially changes the trust boundary, especially if the portrait data contains sensitive or proprietary financial analysis inputs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The save-chart path performs external LLM analysis without any user-facing warning, consent prompt, or transmission notice. This is dangerous because users may believe they are only generating local charts while the tool may transmit derived financial data to third-party services, creating confidentiality, compliance, and auditability concerns.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script reads environment variables for DEEPSEEK and KIMI API keys in order to activate third-party LLM access. Accessing ambient credentials inside a tool that is presented as a financial footnote/portrait utility is risky because it can silently escalate capability from local processing to external networked processing without explicit operator intent.

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest describes a tool for extracting and analyzing financial report footnotes (附注), but this file is built to analyze other annual-report sections such as 经营情况讨论与分析, 报告期内获得的研发成果, 核心竞争力分析, and separately summarize Portrait financial metrics. Those capabilities are materially broader than footnote extraction/analysis and indicate the skill performs general annual-report semantic analysis rather than a footnote-focused function.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The analyzer supports external Moonshot and DeepSeek endpoints and reads API credentials from environment variables, even though the skill is described as a footnote extraction tool. This expands the trust boundary and can cause sensitive report text to be transmitted to third-party services without a clearly justified capability boundary in the skill context.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

The hardcoded Moonshot API endpoint represents an explicit third-party data egress destination available to the script. In this skill context, enabling outbound transmission of report text to a remote provider is security-relevant because the tool handles potentially sensitive company disclosures and does not visibly gate that transfer with consent.

Content

Scanner excerpt · scripts/LLM2Excel3.py (reported line 88)May include surrounding context.

python
self.deepseek_key = os.environ.get("DEEPSEEK_API_KEY", "")

        if self.provider == "moonshot":
            self.api_endpoint = "https://api.moonshot.cn/v1/chat/completions"
            self.api_key = self.moonshot_key
        elif self.provider == "deepseek":
            self.api_endpoint = "https://api.deepseek.com/v1/chat/completions"

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

The hardcoded DeepSeek API endpoint likewise enables transmission of user-supplied company text to an external provider. For a financial-report processing skill, this increases confidentiality and governance risk when not accompanied by explicit disclosure, consent, and provider-specific controls.

Content

Scanner excerpt · scripts/LLM2Excel3.py (reported line 91)May include surrounding context.

python
self.api_endpoint = "https://api.moonshot.cn/v1/chat/completions"
            self.api_key = self.moonshot_key
        elif self.provider == "deepseek":
            self.api_endpoint = "https://api.deepseek.com/v1/chat/completions"
            self.api_key = self.deepseek_key
        else:
            self.ollama_url = ollama_url

External Transmission

Medium
Category
Data Exfiltration
Confidence
96% confidence
Finding

This network call sends assembled messages and report-derived content to a third-party endpoint over the internet. In a financial-report analysis skill, that transmission can expose proprietary or regulated company information if users are not explicitly informed and if data handling controls are absent.

Content

Scanner excerpt · scripts/LLM2Excel3.py (reported line 574)May include surrounding context.

python
if format_schema:
                    payload["response_format"] = {"type": "json_object"}

                response = requests.post(
                    self.api_endpoint,
                    headers=headers,
                    json=payload,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code posts prompts containing company text to an external chat-completions API, and the prompt body can include up to 12,000 characters of annual-report content. In this skill context, users may reasonably expect local extraction/analysis, so silent exfiltration of business text to external LLM providers creates confidentiality and compliance risk.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · scripts/LLM2Excel3.py (reported line 599)May include surrounding context.

python
if format_schema:
                    payload["format"] = format_schema

                response = requests.post(
                    self.api_endpoint,
                    json=payload,
                    timeout=240

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/ReportLinkCrawler2.py (reported line 526)May include surrounding context.

python
report_period: str = '2025年报',
    plate: str = '科创板',
    output_dir: str = './RAWPDF',
    auto_confirm: bool = False,
    max_downloads: int = None,
    stock_codes: list = None,
) -> None:

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/ReportLinkCrawler2.py (reported line 537)May include surrounding context.

python
report_period: str = '2025年报',
    plate: str = '科创板',
    output_dir: str = './RAWPDF',
    auto_confirm: bool = False,
    max_downloads: int = None,
    stock_codes: list = None,
) -> None:

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/ReportLinkCrawler2.py (reported line 552)May include surrounding context.

python
report_period: str = '2025年报',
    plate: str = '科创板',
    output_dir: str = './RAWPDF',
    auto_confirm: bool = False,
    max_downloads: int = None,
    stock_codes: list = None,
) -> None:

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/ReportLinkCrawler2.py (reported line 583)May include surrounding context.

python
report_period: str = '2025年报',
    plate: str = '科创板',
    output_dir: str = './RAWPDF',
    auto_confirm: bool = False,
    max_downloads: int = None,
    stock_codes: list = None,
) -> None:

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest describes the skill as a financial report footnote extraction and analysis tool focused on annual report notes (附注), CNINFO downloads, and visualization. However, this file defines and processes non-footnote '管理层讨论与分析' content such as core competitiveness, risk factors, customers, suppliers, R&D projects, and intellectual property, which expands behavior beyond footnote extraction.

Content

No source excerpt is available for this finding.

Internal Network Request

Medium
Category
Server-Side Request Forgery
Confidence
70% confidence
Finding

Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.

Content

Scanner excerpt · scripts/fn_pipeline.py (reported line 38)May include surrounding context.

python
import urllib.request
    import json
    try:
        req = urllib.request.Request('http://127.0.0.1:11434/api/tags', method='GET')
        with urllib.request.urlopen(req, timeout=5) as resp:
            data = json.loads(resp.read())
            models = [m['name'] for m in data.get('models', [])]

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The command-line interface requires stock_name as 'Company name in Chinese' and defaults the plate argument to a Chinese value, while the script also emits mixed Chinese-only status text in multiple user-facing messages. This imposes a specific language/locale on users without opt-in or an alternative, which matches the policy concern for forced language selection.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.