Back to skill

Security audit

Doc Processor

Security checks for vulnerabilities and agentic risk

Overview

This document-processing skill is mostly local, but it has under-disclosed document retention and unsafe PDF/file-writing paths that users should review before installing.

Install only if you are comfortable with a local document tool that can create, overwrite, convert, and merge files, and review setup.sh before running it, especially any sudo commands or custom package indexes. Avoid using the generation/template-learning APIs with confidential documents unless you accept persistent copies under a user-templates directory, and avoid optional PDF generation backends until the HTML escaping and temporary-file handling are fixed.

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)

T08 · Insecure Dependencies

Warning
Location
requirements.txt:7
Finding

Unpinned Dependencies and Unrestricted Package Index Selection

Content
View full analysis
=1.1.0 # Excel processing openpyxl>=3.1.2 pandas>=2.1.0 # Utilities python-dotenv>=1.0.0 ``` The installation script resolves these dependencies from a configurable index: ```bash # Default to official PyPI PIP_INDEX="${PIP_INDEX_URL:-https://pypi.org/simple}" # Allow a package index to be supplied as a command-line argument if [ -n "$1" ]; then PIP_INDEX="$1" fi # Upgrade packaging tools echo "📦 Upgrading pip tools..." pip install --upgrade pip setuptools wheel -q --index-url "$PIP_INDEX" # Install Python dependencies if [ -f "$SCRIPT_DIR/requirements.txt" ]; then echo "📦 Installing Python dependencies from $PIP_INDEX..." pip install -r "$SCRIPT_DIR/requirements.txt" --index-url "$PIP_INDEX" echo "✅ Python dependencies installed" else echo "❌ requirements.txt was not found" exit 1 fi ``` ### Technical Analysis The dependency declarations use open-ended minimum versions rather than exact, audited versions. Consequently, every installation may resolve to a newer dependency release that was not present during the Skill audit. The setup script also accepts the package index through either `PIP_INDEX_URL` or its first command-line argument. It does not enforce an approved hostname, verify hashes, or require a lockfile. An environment variable inherited from a compromised shell, CI runner, or parent agent can therefore redirect installation to an attacker-controlled package repository. Python distributions may execute code during installation, and installed modules execute code when imported. The Skill imports these packages during normal startup, so a substituted dependency can obtain code execution even if the document-processing operation itself is benign. ### At ...[truncated 1139 chars]
Remediation
View remediation
openpyxl== pandas== python-dotenv== ``` 2. Generate a complete lockfile that includes transitive dependencies. 3. Record cryptographic hashes and install with: ```bash pip install --require-hashes -r requirements.lock ``` 4. Reject package indexes that do not use HTTPS or whose hosts are not on an explicit allowlist. 5. Do not silently inherit `PIP_INDEX_URL` in security-sensitive automated installations. 6. Avoid unconditional upgrades of `pip`, `setuptools`, and `wheel`; pin and audit those tools separately. 7. Run installation in a minimally privileged environment with no unnecessary secrets or write access. 8. Add dependency vulnerability and provenance checks to the release process. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
pdf_generator.py:81
Finding

Unescaped HTML in WeasyPrint Rendering Permits SSRF and Local Resource Access

Content
View full analysis
str: try: from weasyprint import HTML except ImportError: raise RuntimeError("WeasyPrint is not installed") html_content = self._generate_html(content) HTML(string=html_content).write_pdf(str(output)) logger.info(f"PDF generation complete: {output.name}") return str(output.absolute()) def _generate_html(self, content: Dict) -> str: title = content.get('title', '') title_html = f"

{title}

" if title else '' paragraphs_html = ''.join( f"

{para}

" for para in content.get('paragraphs', []) ) return f"""{title}@page {{ size: A4; margin: 2.54cm; }} body {{ font-family: "SimSun", serif; font-size: 12pt; line-height: 1.8; }} h1 {{ font-size: 22pt; text-align: center; }}{title_html}{paragraphs_html}""" ``` ### Technical Analysis The title and paragraph fields are interpolated directly into an HTML document without HTML escaping or sanitization. They are therefore interpreted as active markup rather than plain document text. WeasyPrint resolves resources referenced by supported HTML and CSS constructs while rendering. Injected markup can request external HTTP resources or attempt to load local resources through absolute URLs. No custom URL fetcher or scheme and destination policy prevents access to: - Loopback services - Private network addresses - Link-local services - Other internal HTTP endpoints - Local `file:` resources readable by the process Even when the retrieved resource is not visibly rendered, the request itself can produce a server-side network callback. Renderable local resources may also be ...[truncated 1360 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
pdf_generator.py:54
Finding

Predictable Temporary DOCX Path Overwrites and Deletes Existing Files

Content
View full analysis
str: try: from docx2pdf import convert except ImportError: raise RuntimeError("docx2pdf is not installed") temp_docx = output.with_suffix('.docx') try: from docx import Document from docx.shared import Pt, Cm from docx.enum.text import WD_ALIGN_PARAGRAPH doc = Document() section = doc.sections[0] section.page_width = Cm(21) section.page_height = Cm(29.7) if 'title' in content: heading = doc.add_heading(content['title'], 0) heading.alignment = WD_ALIGN_PARAGRAPH.CENTER if 'paragraphs' in content: for para_text in content['paragraphs']: doc.add_paragraph(para_text) doc.save(temp_docx) convert(str(temp_docx), str(output)) logger.info(f"PDF generation complete: {output.name}") return str(output.absolute()) finally: if temp_docx.exists(): temp_docx.unlink() ``` ### Technical Analysis The temporary path is deterministically derived from the requested PDF output by replacing its extension with `.docx`. It is not created through a secure temporary-file API, and the code does not check whether that path already contains a legitimate user file. For an output such as `/documents/report.pdf`, the temporary path becomes `/documents/report.docx`. `doc.save(temp_docx)` overwrites that file if it exists. The `finally` block then deletes it regardless of whether conversion succeeds. The unsafe cleanup also runs after exceptions. Consequently, an existing DOCX can be destroyed even if PDF conversion fails. ### Attack Path 1. A legitimate document exists at `/documents/report.docx`. 2. A cal ...[truncated 1052 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
doc_processor.py:1472
Finding

Automatic Persistent Duplication of User Templates and Generated Documents

Content
View full analysis
GenerationResult: """Intelligent document generation""" if template_path: template_info = self._save_user_template( template_path, user_request ) selected_template = template_info else: selected_template = self._match_historical_template(user_request) if selected_template: if not output_path: timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") output_path = self.workspace / f"generated_{timestamp}.docx" filled_path = self.fill_template( selected_template.path, content or {}, str(output_path) ) self._save_as_user_template(filled_path, user_request) return GenerationResult( output_path=filled_path, template_used=selected_template, stats={'method': 'template'} ) else: raise NotImplementedError("Style Guide generation is not implemented") def _save_user_template( self, template_path: str, user_request: str ) -> TemplateInfo: """Save user template""" import hashlib template = Path(template_path) file_hash = hashlib.md5(template.read_bytes()).hexdigest()[:8] timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") template_id = f"tpl_{timestamp}_{file_hash}" saved_path = ( self.user_template_dir / "templates" / f"{template_id}{template.suffix}" ) shutil.copy2(template, saved_path) content_type = self._infer_content_type_from_request(user_request) template_info = TemplateInfo( path=str(saved_path), ...[truncated 3856 chars]
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (99)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

该代码块并不是文档处理引擎的实现,而是一个综合测试脚本,主要用途是对 DocumentProcessor 的各项能力进行回归测试和结果汇总。因此其主要目的与声明的“专注文档处理”的技能功能本体并不一致。虽然测试内容覆盖的能力大多与文档处理声明相符,但代码本身执行的是测试、创建临时目录、打印报告和退出状态码等测试框架行为。此外,初始化处理器时传入了 ai_service_type='simple',这与声明中“v2.7.11 移除 AI 功能”存在直接不一致信号。综合判断为描述与代码行为存在实质性不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

该代码片段展示的不是核心文档处理实现,而是一个 v2.7.4 测试脚本,用于验证转换、缓存、性能监控和批量处理等能力,这些总体上与文档处理描述大体相关。但存在一个关键不一致:声明中明确写明 v2.7.11“移除 AI 功能”,而测试脚本在实例化处理器时仍传入 ai_service_type='simple',说明 AI 相关配置/接口至少仍然存在于该版本代码路径中。即便该参数未在片段中直接用于推理或生成,其存在与“已移除 AI 功能”的表述构成明显描述-行为不一致。此外,片段本身的直接用途是测试而不是文档处理主逻辑,因此与所宣称的技能主用途也不完全一致。

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README states that AI features were removed in v2.7.11, but nearby sections still present AI-based matching, intelligent generation, and related capabilities as active functionality. This inconsistency can mislead users and downstream agents about what the skill actually does, causing unsafe trust assumptions, incorrect routing of sensitive content, or accidental invocation expectations around removed features.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The release notes make contradictory claims about 'AI deep integration' while also stating elsewhere that AI calls were not actually implemented and that AI functionality was later removed. This is a genuine security-relevant documentation integrity issue because users or downstream agents may rely on nonexistent or deprecated AI behavior when making trust, deployment, or data-handling decisions.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The document advertises AI summarization, expansion, and plan-generation features that conflict with the skill metadata stating AI functionality has been removed and that the skill is focused on document processing. In an agent ecosystem, misleading capability documentation can cause unsafe invocation patterns, incorrect data exposure assumptions, or policy bypass if operators believe content will be sent to or processed by AI components when it is not, or vice versa.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The release note explicitly states that AI-related functionality is no longer applicable, yet the same document continues to document and promote AI request-analysis features. This inconsistency can mislead users, operators, or downstream agents into believing deprecated or removed AI capabilities still exist, increasing the risk of unsafe assumptions, misconfiguration, or unintended invocation paths.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The release notes acknowledge that formulas may be overwritten and formatting or conditional formatting may be lost after filling templates. Because these behaviors can affect user data integrity, the markdown should warn users earlier and more explicitly before they adopt the feature, not only list them as known issues near the end.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill advertises installation and usage paths that involve shell commands, file reads/writes, and external package retrieval, but it does not declare any explicit tool scope or permissions boundary. In an agent setting, this can cause the skill to receive broader capabilities than users expect, increasing the chance of unsafe file modification, command execution, or network/package access without clear consent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The natural-language instructions and usage guidance in this file are presented entirely in Chinese, which effectively forces a specific language for users. The file does not offer an alternative language, opt-in choice, or state that the skill is intentionally limited to a Chinese-speaking or region-specific context.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
72% confidence
Finding

The manifest includes an installation command using sudo apt install, which requires elevated privileges and may be executed by an installer or operator with insufficient scrutiny. Any workflow that normalizes privileged execution increases the blast radius of supply-chain compromise, command tampering, or operator error.

Content

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

md
platforms: ["darwin"]
      - id: apt-poppler
        kind: system
        command: "sudo apt install -y poppler-utils"
        bins: ["pdftotext", "pdfinfo"]
        label: "Install poppler-utils (apt)"
        platforms: ["linux"]

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

The documentation instructs users to run sudo apt install poppler-utils, encouraging elevated execution during setup. Although common for package installation, this is still security-relevant because it conditions users or automation to grant root access to fulfill skill prerequisites.

Content

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

bash
# Linux (Debian/Ubuntu)
sudo apt install poppler-utils

# Linux (RHEL/CentOS)
sudo yum install poppler-utils

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

The sudo yum install poppler-utils example likewise requires root privileges and may be copied into automation or executed without sufficient review. In hostile or tightly controlled environments, normalizing privileged commands can amplify the effect of mistakes or repository compromise.

Content

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

md
sudo apt install poppler-utils

# Linux (RHEL/CentOS)
sudo yum install poppler-utils

# macOS
brew install poppler

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The documented write, merge, and convert commands produce output files but do not prominently warn that existing local files may be created or overwritten. In an agent-driven workflow, ambiguous output semantics can lead to accidental data loss or modification of sensitive workspace files if paths are reused or attacker-influenced.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This Python file contains natural-language strings in Chinese, including the module docstring and the default progress description. The policy flags language or locale constraints when the skill forces a specific language without offering user choice or documenting a justified locale-specific scope.

Content

No source excerpt is available for this finding.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · batch_processor.py (reported line 38)May include surrounding context.

python
def __init__(self, total: int, description: str = "处理中"):
        self.total = total
        self.description = description
        self.start_time = __import__('time').time()
        self.current = 0
        self.success = 0
        self.failed = 0

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · check_deps.py (reported line 12)May include surrounding context.

python
def check_system_cmd(cmd):
    """检查系统命令"""
    try:
        result = subprocess.run(
            [cmd, '--version' if cmd != 'pdfinfo' else '-v'],
            capture_output=True,
            timeout=5

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module-level comments at L0048-L0049 state that AI functionality has been removed and the skill now focuses only on document processing. However, later docstrings/comments still label methods as "AI 增强版" and describe AI analysis/summarization behavior, creating direct intent/documentation contradictions about whether AI features remain in this skill.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The class and initializer docs at L0386-L0393 say the adapter was simplified and AI functionality was removed. Yet the later, effective _adapt_summary definition at L0447-L0491 overrides the earlier one and is explicitly documented as "v2.1 AI 增强版" with comments about AI summarization, contradicting the stated removal of AI features.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The write path creates parent directories and then dispatches to file-writing helpers, but there is no confirmation prompt and no user-facing disclosure that existing files may be overwritten. Similar silent writes occur in downstream save operations, making this a safety-relevant behavior for user data.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · doc_processor.py (reported line 897)May include surrounding context.

python
cmd.extend(['-l', pages.split('-')[1]])
        cmd.extend([str(path), '-'])

        result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
        if result.returncode != 0:
            raise Exception(f"pdftotext 失败:{result.stderr}")

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · doc_processor.py (reported line 911)May include surrounding context.

python
def _get_pdf_pages(self, path: Path) -> int:
        """获取 PDF 页数"""
        try:
            result = subprocess.run(
                ['pdfinfo', str(path)],
                capture_output=True,
                text=True,

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest states AI features were removed in v2.7.11, but functions such as generate ("智能文档生成"), _match_historical_template comments ("AI 分析请求"), and _analyze_request ("AI 分析用户请求") still claim AI-driven behavior. The implementation only performs deterministic local scoring and keyword inference, so the documentation actively misrepresents the skill's behavior and intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code persists user-provided documents into a template store and updates a registry without explicit consent or clear disclosure. In document-processing workflows, retained templates may contain sensitive business or personal information, so silent retention materially increases confidentiality risk.

Content

No source excerpt is available for this finding.

Tainted flow: 'saved_path' from pathlib.Path.read_bytes (line 1501, file read) → shutil.copy2 (file write)

Medium
Category
Data Flow
Confidence
83% confidence
Finding

The method copies an arbitrary user-supplied template path into a persistent template store without first constraining the source path to the workspace or an allowlisted directory. In an agent setting, this can be abused to read and retain sensitive local files from elsewhere on the filesystem if an attacker can influence template_path.

Content

Scanner excerpt · doc_processor.py (reported line 1502)May include surrounding context.

python
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        template_id = f"tpl_{timestamp}_{file_hash}"
        saved_path = self.user_template_dir / "templates" / f"{template_id}{template.suffix}"
        shutil.copy2(template, saved_path)
        content_type = self._infer_content_type_from_request(user_request)
        template_info = TemplateInfo(path=str(saved_path), style=StyleDefinition(), content_type=content_type, usage_count=1, last_used=datetime.now().isoformat())
        self._update_registry(template_info)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

Automatically copying every generated document into a historical template repository creates undisclosed secondary storage of possibly sensitive output. That expands the attack surface and can lead to unintended reuse or later disclosure of confidential generated content.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.