Back to skill

Security audit

环评知识库提炼

Security checks for vulnerabilities and agentic risk

Overview

This is a local Chinese-language EIA document extraction skill that has quality and dependency hygiene issues, but I found no hidden, credential-seeking, persistent, destructive, or exfiltrating behavior.

Install only if you are comfortable running a local, Chinese-language report parser that writes CSV and text files to the chosen output directory. Use a dedicated empty output folder, avoid opening generated CSVs from untrusted reports in a spreadsheet until formula-prefix sanitization is added, and prefer pinned dependencies or a reviewed lockfile for production use.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main.py:315
Finding

CSV Formula Injection Through Untrusted Report Data

Content
View full analysis

Vulnerability Details

File Location: scripts/main.py:315-324 and scripts/extract_pollutant_info.py:75-84
Vulnerability Type: CSV formula injection
Risk Level: Medium

Vulnerable Code

scripts/main.py:315-324:

python
for idx, row in df.iterrows():
    if idx == 0:  # Skip the header
        continue

    record = {}
    # Extract fields according to the table structure
    for col in df.columns:
        val = row.get(col)
        if val and not pd.isna(val):
            record[str(col)] = str(val).strip()

scripts/extract_pollutant_info.py:75-84:

python
# Collect all possible field names
all_fieldnames = set()
for record in data:
    all_fieldnames.update(record.keys())

# Convert to an ordered list
fieldnames = list(all_fieldnames)

with open(filename, 'w', newline='', encoding='utf-8-sig') as f:
    writer = csv.DictWriter(f, fieldnames=fieldnames, extrasaction='ignore')
    writer.writeheader()
    writer.writerows(data)

Technical Analysis

The application processes user-supplied PDF and DOCX tables and copies cell values into CSV records without neutralizing spreadsheet formula prefixes. A value beginning with =, +, -, or @ is written unchanged.

CSV itself does not execute code, but common spreadsheet applications may interpret such values as formulas when a generated file is opened. Depending on the spreadsheet application and its security settings, malicious formulas may create deceptive content, initiate external requests, expose spreadsheet-accessible information, or invoke dangerous legacy functionality.

CSV quoting performed by Python's csv module does not prevent this issue because spreadsheet applications still evaluate a quoted cell's decoded content as a formula.

Attack Path

  1. An attacker creates an environmental report containing a table cell whose value starts with a spreadsheet formula character, such as `=HYPER ...[truncated 1112 chars]
Remediation
View remediation

Remediation Suggestions

Implement a centralized CSV-cell sanitizer and apply it to every field and header before serialization. At minimum, neutralize values whose first non-whitespace character is =, +, -, or @. Prefixing such values with a single quote is commonly used for spreadsheet-oriented CSV output, although the exact strategy should be verified against supported spreadsheet applications.

Example:

python
DANGEROUS_CSV_PREFIXES = ("=", "+", "-", "@")

def sanitize_csv_cell(value):
    if value is None:
        return value

    text = str(value)
    if text.lstrip().startswith(DANGEROUS_CSV_PREFIXES):
        return "'" + text
    return text

def sanitize_record(record):
    return {
        sanitize_csv_cell(key): sanitize_csv_cell(value)
        for key, value in record.items()
    }

Sanitize records before calling writer.writerows():

python
safe_data = [sanitize_record(record) for record in data]
writer.writerows(safe_data)

Apply equivalent protection to every CSV exporter in:

  • scripts/extract_pollutant_info.py
  • scripts/extract_emission_standards.py
  • scripts/extract_source_calculation.py

Add regression tests covering leading formula characters, leading whitespace before formula characters, tabs, carriage returns, multiline cells, and ordinary negative numeric values. Where preservation of numeric types is important, define an explicit schema rather than broadly treating all values beginning with - as malicious.

Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

描述强调一个通用的环评报告知识库提炼工具,并特别声明支持 PDF/DOCX 解析;但实际代码是一个单用途脚本框架,专注于提取污染物排放标准信息并保存为 CSV。代码没有任何 PDF/DOCX 解析实现,也没有显示对环评报告其他类型结构化知识的提取能力。因此,虽然代码与环评报告信息抽取这一大方向相关,但其实际能力和范围明显小于且不同于声明,构成描述与行为不一致。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

声明描述的是一个可从环评报告表中提取结构化知识库文件、并支持 PDF/DOCX 解析的完整工具;但提供的代码只是一个面向“污染因子信息”的提取脚本雏形。它没有任何 PDF 或 DOCX 解析实现,入口仅打开 TXT 文件读取文本;多个关键提取函数使用 pass,说明实际并未实现主要能力。因此,代码实际行为与声明用途存在明显不一致,属于高置信度 mismatch。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

该描述与代码存在实质不一致。虽然二者都与环评报告中的结构化信息提取有关,但代码的实际范围明显更窄,只处理源强核算相关信息,而不是泛化的“知识库提炼工具”。更重要的是,声明特别强调“支持PDF/DOCX解析”,但代码中没有任何相关库、解析逻辑或调用,只有从普通文本文件读取的示例。此外,提取逻辑本身还是占位实现,真正完成的主要是将预期结构写入 CSV。因此,描述高估并偏离了该代码片段的实际能力。

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The module docstrings and user-facing descriptions are entirely in Chinese, which effectively forces a specific language without opt-in. Under the stated policy, locale or language restrictions should either offer user choice or be clearly documented as justified for a region-specific tool.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module docstring and each extractor docstring state that the script extracts pollutant source-strength calculation information from EIA reports. In reality, all four extraction functions only initialize an empty list and return it without implementing any parsing logic, which directly contradicts the documented intent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The module docstring and all user-facing descriptions are written only in Chinese, which imposes a specific language on users without any opt-in or alternative. Under the policy for natural-language violations, a forced language or locale choice should be documented as optional or justified as region-specific.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

This markdown file describes the outputs as five generated CSV knowledge-base files, which implies file creation affecting the user's filesystem. Under the markdown-specific missing-warning rule, the description should clearly disclose this file-writing behavior and any overwrite/output-directory implications, but no explicit warning is provided.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The CSV headers and example row are entirely in Chinese, and there is no accompanying indication that the skill supports other languages or that Chinese-only output is an intentional, justified locale constraint. Under the stated policy, forcing a specific language without user opt-in can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency is specified with a lower bound only (pymupdf>=1.23.0), which allows future unreviewed versions to be installed and makes builds non-reproducible. In a document-parsing skill that handles PDFs, supply-chain risk matters because parser libraries frequently process attacker-controlled files and a vulnerable or compromised future release could be pulled in automatically.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
pymupdf>=1.23.0
pandas>=1.5.0
python-docx>=0.8.11

Unverifiable Dependency: pymupdf has 2 known advisory(ies) (CVE-2026-3029 (PyMuPDF has a path traversal in _main_.py); CVE-2026-3029 (PyMuPDF has a path traversal in _main_.py)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
90% confidence
Finding

PyMuPDF has known advisories and the manifest does not pin a version, so it is impossible to verify whether deployment will include a vulnerable release. This is more concerning here because the skill explicitly parses PDFs, making a parser dependency part of the attack surface for potentially untrusted files.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The pandas dependency is also unpinned except for a minimum version, so the installed package may vary over time and between environments. While this is not an immediate exploit by itself, it increases supply-chain and stability risk by permitting unreviewed releases to enter production.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
pymupdf>=1.23.0
pandas>=1.5.0
python-docx>=0.8.11

Unverifiable Dependency: pandas has 1 known advisory(ies) (CVE-2020-13091 (** DISPUTED ** pandas through 1.0.3 can unserialize and execute commands from an)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
74% confidence
Finding

The manifest does not pin pandas, so the project cannot demonstrate that the installed version avoids the cited advisory. Although the referenced pandas issue may be context-dependent and disputed, leaving the version unresolved still creates uncertainty and weakens supply-chain assurance.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

python-docx is defined with only a minimum version, which prevents determining exactly what code will be installed and whether it includes known fixes. Because this skill parses DOCX files, dependency hygiene is especially important for a library that may process untrusted document content.

Content

Scanner excerpt · requirements.txt (reported line 3)May include surrounding context.

text
pymupdf>=1.23.0
pandas>=1.5.0
python-docx>=0.8.11

Unverifiable Dependency: python-docx has 2 known advisory(ies) (CVE-2016-5851 (Improper Restriction of XML External Entity Reference in python-docx); CVE-2016-5851 (python-docx before 0.8.6 allows context-dependent attackers to conduct XML Exter)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
95% confidence
Finding

python-docx has known historical XXE-related advisories, and without version pinning there is no way to confirm that only fixed releases are installed. In a DOCX-processing tool, XML parser issues are directly relevant because attackers may be able to deliver crafted documents to trigger vulnerable parsing behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

This is a natural-language policy concern because the module docstring presents the skill entirely in Chinese and does not indicate that users may choose another language or locale. Under the stated policy, forcing a specific language without opt-in should be flagged unless the locale constraint is explicitly justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This code writes extracted data directly to the path provided by filename using write mode, which can overwrite an existing file. Although the function docstring says it saves data to CSV, there is no confirmation prompt, warning comment, or user-facing log indicating that an output file will be created or replaced.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The manifest frames the skill as a knowledge-extraction tool for EIA reports, which clearly covers parsing and structuring report content. This module also persists multiple CSV files to disk, an additional behavior not stated in the description; while related to the purpose, it is a broader operational behavior than pure extraction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

This codebase presents its primary description and user-facing messaging in Chinese, and the CLI/help output is likewise written in Chinese. Under the policy, forcing a specific language without user opt-in is a natural-language locale violation unless the constraint is explicitly documented and justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The usage instructions describe running the tool and choosing an output directory, but they do not clearly warn users that execution will create multiple files on disk, including reports and CSV outputs. This can lead to unintended file creation, cluttering sensitive directories, or accidental writes in shared/workspace locations, especially when users invoke the skill on untrusted or production paths.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.