Back to skill

Security audit

Ofd Reader skill

Security checks for vulnerabilities and agentic risk

Overview

This is a straightforward OFD document conversion skill with disclosed local file output and an optional dependency installer, and I found no hidden persistence, exfiltration, or deceptive behavior.

Install only if you are comfortable using a local converter on OFD files. Avoid running the optional dependency installer unless needed, process only trusted OFD documents when possible, and write output to a deliberate workspace path so existing files are not overwritten.

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)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ofd_to_text.py:29
Finding
Unbounded Processing of Untrusted OFD Archives<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ofd_to_text.py:29-39`; `scripts/ofd_to_markdown.py:28-34` **Vulnerability Type**: Uncontrolled resource consumption through archive decompression and XML parsing **Risk Level**: Medium ### Vulnerable Code `scripts/ofd_to_text.py:29-39`: ```python with zipfile.ZipFile(ofd_path, 'r') as zip_ref: # 获取所有 XML 文件 file_list = zip_ref.namelist() # OFD 文件结构:根目录有 OFD.xml,内容在 Doc_0/ 下 # 首先读取 OFD.xml 获取文档结构 ofd_xml_files = [f for f in file_list if f.endswith('.xml') and 'Doc_' in f] for xml_file in ofd_xml_files: try: with zip_ref.open(xml_file) as xml_file_obj: ``` `scripts/ofd_to_markdown.py:28-34`: ```python with zipfile.ZipFile(self.ofd_path, 'r') as zip_ref: file_list = zip_ref.namelist() # 查找文档内容文件 doc_files = [f for f in file_list if f.endswith('.xml') and 'Doc_' in f] for doc_file in sorted(doc_files): self._process_document(zip_ref, doc_file) ``` The selected entries are subsequently parsed using `xml.etree.ElementTree.parse()` without resource limits. ### Technical Analysis Both converters treat OFD documents as ZIP archives and process every archive entry whose name ends in `.xml` and contains `Doc_`. They do not enforce limits on: - The number of archive entries - The uncompressed size of individual entries - The aggregate uncompressed size - The ratio between compressed and uncompressed sizes - XML document size, nesting depth, or element count - Total conversion time or memory consumption An attacker can construct an OFD archive containing highly compressible XML data, a large number of qualifying entries, or XML documents with excessive structural complexity. Opening and parsing those entries can consume substantial CPU and memory even when the supplied archive itself is relatively small. The scripts do not extract entries to the filesystem, so conventional ZIP path traversal is not demonstrated. The relevant weakne ...[truncated 1111 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Inspect every candidate entry with `ZipFile.infolist()` before opening it. 2. Reject archives that exceed explicit limits for: - Total entry count - Number of XML entries - Maximum uncompressed size per entry - Maximum aggregate uncompressed size - Maximum compression ratio 3. Maintain a cumulative byte counter while reading entries rather than relying only on ZIP metadata. 4. Parse XML incrementally with `ElementTree.iterparse()` and clear processed elements to reduce memory use. 5. Enforce application-level limits on XML depth, element count, text length, and conversion time. 6. Process untrusted documents in a restricted worker with operating-system CPU and memory limits. 7. Return an explicit validation error when any configured resource limit is exceeded. ]]>

T08 · Insecure Dependencies

Note
Location
scripts/install_dependencies.py:11
Finding
Unpinned Third-Party Package Installation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install_dependencies.py:11-22` **Vulnerability Type**: Unsafe dependency resolution from a mutable package source **Risk Level**: Low ### Vulnerable Code ```python dependencies = [ # OFD 处理可能需要的库 # ofdrw 是一个 OFD 读写库 "ofdrw>=0.3.0", ] print("正在安装 OfdReader skill 的依赖...") for package in dependencies: print(f"安装 {package}...") try: subprocess.check_call([sys.executable, "-m", "pip", "install", package]) ``` ### Technical Analysis The installer permits any `ofdrw` version greater than or equal to `0.3.0`. It does not pin an audited release, verify artifact hashes, constrain transitive dependencies, or specify an approved package index. Consequently, installation behavior can change after the Skill has been reviewed. Pip may select a future release or resolve packages from a user-configured or attacker-influenced index. Python package installation may execute build backend or setup logic with the privileges of the user running the installer. The subprocess invocation uses an argument array and a hardcoded package specification, so shell command injection is not present. The risk is specifically the mutable and insufficiently verified dependency supply chain. ### Attack Path 1. A user invokes `scripts/install_dependencies.py`. 2. Pip connects to its configured package index and resolves `ofdrw>=0.3.0` and any transitive dependencies. 3. A compromised future release, compromised index, or malicious package supplied through an unsafe index configuration is selected. 4. Pip downloads and installs the selected artifact. 5. Malicious build or installation logic executes with the privileges of the user who launched the script, or malicious package code becomes available for later execution. This path depends on compromise or attacker influence over package distribution or pip index configuration; the audited repository itself does not contain evidence that `ofdrw` is malici ...[truncated 492 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the installer if the dependency is genuinely optional and unused by the core converters. 2. Otherwise, pin an audited exact version instead of using a lower-bound constraint, for example `ofdrw==<audited-version>`. 3. Pin all transitive dependencies in a reviewed lock file. 4. Require cryptographic hashes with pip's `--require-hashes` option. 5. Configure an explicit, organization-approved HTTPS package index rather than relying on ambient pip configuration. 6. Prefer prebuilt, verified wheels and disable source builds where operationally possible. 7. Run package installation in an isolated virtual environment without administrator privileges. 8. Add an automated dependency review and update process so pinned versions receive controlled security updates. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • 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 (13)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
声明描述包含两项核心能力:1)提取纯文本;2)转换为 Markdown,并保留基本格式如标题、段落、表格。代码确实实现了基础的 OFD 文本提取,但没有任何 Markdown 生成逻辑,也没有对文档结构、段落层级、标题识别或表格解析的处理。它只是扫描部分 XML 文件中的 TextCode/TextContent 文本并拼接输出。因此,描述对该 skill 的能力有实质性夸大,尤其是“转换为 Markdown 格式”和“处理基本版式结构”并未在代码中体现,构成描述与行为不一致。

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill documents shell execution of local Python scripts and writing output files, but it does not declare any explicit tool scope such as allowed-tools or permissions. This creates an authorization gap where the runtime capabilities required by the skill are broader than what the manifest transparently communicates, increasing the chance of unintended command execution or file writes when the skill is invoked.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
for package in dependencies:
        print(f"安装 {package}...")
        try:
            subprocess.check_call([sys.executable, "-m", "pip", "install", package])
            print(f"  {package} 安装成功")
        except subprocess.CalledProcessError as e:
            print(f"  警告: {package} 安装失败: {e}")
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
This script fetches and installs packages from pip at runtime, which introduces a software supply-chain risk unrelated to the core document-reading logic. If package resolution is tampered with, a malicious or compromised dependency could execute code during installation, expanding the skill from local file processing into network-backed code acquisition and execution.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
Manifest 描述该 skill 支持从 OFD 提取文本并转换为 Markdown,且可处理标题、段落、表格等基本格式;但此文件只提取 TextCode/TextContent 并输出纯文本,没有任何 Markdown 结构化转换逻辑。与此同时,main() 还提供将结果写入任意输出路径的能力,这比“读取”更接近通用文件导出行为。

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The script accepts an arbitrary output path and writes extracted content there without constraining the destination. In an agent/tooling context, this expands a document-reading skill into a local file write primitive, which can be abused to overwrite user files, place data in sensitive locations, or enable follow-on attacks if the caller can influence the path.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The entire reference file is written in Chinese and presents the material solely in that language, with no indication that users can select another language or that the localization is optional. Under the policy for natural-language violations, forcing a specific language without user opt-in can be a concern unless the locale constraint is clearly documented and justified.

Natural-Language Policy Violations

Low
Confidence
98% confidence
Finding
The docstring, function docstring, and all printed user-facing messages are in Chinese, which imposes a specific language on users. The file does not indicate that the skill is region-specific or provide any opt-in or fallback language behavior.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
This is a code file, so SQP-3 applies to natural-language text in docstrings and messages. The file presents its description and usage entirely in Chinese and does not offer an alternative language or indicate that the tool is intentionally region-specific, which can violate language/locale policy requirements.

Intent-Code Divergence

Low
Confidence
72% confidence
Finding
The top-level docstring presents the tool as converting OFD to Markdown while preserving basic structure, implying faithful processing. However, `_process_document` suppresses all exceptions with `pass`, which can silently skip document content and produce incomplete output without indicating that preservation/conversion failed.

Description-Behavior Mismatch

Low
Confidence
84% confidence
Finding
The manifest emphasizes extracting text from OFD and converting it to Markdown, which suggests a reader/converter role. The code also performs filesystem write operations to a user-specified output path, adding a persistence side effect not stated in the manifest description.

Intent-Code Divergence

Low
Confidence
84% confidence
Finding
文件头和函数 docstring 都将该脚本描述为 OFD 文本提取工具,强调的是读取/提取语义。实际 main() 除了提取外,还会在提供第二个参数时执行文件写入,这与“仅提取”的表述存在意图层面的偏差。

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The file’s docstrings and CLI messages are written exclusively in Chinese, including usage and error output. This imposes a specific language on users without any opt-in or indication that the tool is intended only for a Chinese-speaking or region-specific context.

Static analysis

No suspicious patterns detected.