Back to skill

Security audit

document-reader

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent document reader, but its archive handling and install instructions create security risks users should review before installing.

Review this skill before installing. Use it only on files you intend the agent to read, avoid running it on untrusted oversized archives, and install dependencies in an isolated virtual environment or container rather than following the system-wide pip command as written.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/document_reader.py:227
Finding

Predictable Temporary Files Allow Symlink-Based File Overwrite

Content
View full analysis

Vulnerability Details

File Location: scripts/document_reader.py:227-237, scripts/document_reader.py:278-288, scripts/document_reader.py:324-334, and scripts/document_reader.py:372-382
Vulnerability Type: Predictable temporary filename and unsafe file creation
Risk Level: High

Vulnerable Code

The ZIP archive handler uses an archive-controlled basename to construct a predictable path:

python
temp_path = f"/tmp/doc_reader_{os.path.basename(inner_path)}"
with open(temp_path, 'wb') as tf:
    tf.write(content_bytes)

try:
    result = self.read_document(temp_path)
    result['archive_path'] = zip_path
    result['inner_path'] = inner_path
    return result
finally:
    if os.path.exists(temp_path):
        os.unlink(temp_path)

The TAR archive handler repeats the same pattern:

python
temp_path = f"/tmp/doc_reader_{os.path.basename(inner_path)}"
with open(temp_path, 'wb') as tf_tmp:
    tf_tmp.write(content_bytes)

try:
    result = self.read_document(temp_path)
    result['archive_path'] = tar_path
    result['inner_path'] = inner_path
    return result
finally:
    if os.path.exists(temp_path):
        os.unlink(temp_path)

The RAR archive handler also uses the same predictable path:

python
temp_path = f"/tmp/doc_reader_{os.path.basename(inner_path)}"
with open(temp_path, 'wb') as tf_tmp:
    tf_tmp.write(content_bytes)

try:
    result = self.read_document(temp_path)
    result['archive_path'] = rar_path
    result['inner_path'] = inner_path
    return result
finally:
    if os.path.exists(temp_path):
        os.unlink(temp_path)

The 7-Zip archive handler repeats the vulnerable construction:

python
temp_path = f"/tmp/doc_reader_{os.path.basename(inner_path)}"
with open(temp_path, 'wb') as tf_tmp:
    tf_tmp.write(content_bytes)

try:
    result = self.read_document(temp_path)
    result['archive_path']
...[truncated 2382 chars]
Remediation
View remediation

Remediation Suggestions

  • Replace manually constructed /tmp paths with tempfile.NamedTemporaryFile or a private tempfile.TemporaryDirectory.
  • Use random, operating-system-generated names and restrictive permissions.
  • Keep the securely created file descriptor open while writing the archive member.
  • Do not reopen a pathname after creation unless ownership and file type have been validated.
  • Ensure the temporary object is not a symbolic link and is owned by the current process account.
  • Create a separate private temporary directory for each invocation to prevent collisions between concurrent processes.
  • Run document parsing under a dedicated, unprivileged account with access only to required inputs.
  • Apply the correction consistently to the ZIP, TAR, RAR, and 7-Zip handlers.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:39
Finding

Unpinned Dependencies Are Installed into the System Python Environment

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:39
Vulnerability Type: Unsafe dependency installation guidance
Risk Level: Medium

Vulnerable Code

bash
pip install textract python-docx openpyxl python-pptx rarfile py7zr --break-system-packages

Technical Analysis

The documented installation command installs several third-party packages without pinning reviewed versions or verifying package hashes. Consequently, the installed code can vary over time according to the latest package and transitive dependency releases available when the command is run.

Python package installation may execute package build and installation logic. A compromised package release, compromised transitive dependency, or unexpected dependency-resolution result could therefore execute code during installation or introduce malicious runtime behavior.

The --break-system-packages option explicitly bypasses protections intended to prevent pip from modifying a distribution-managed Python environment. This increases the possibility of package conflicts, replacement of system-managed components, and disruption of other applications that share the interpreter.

Attack Path

  1. A listed dependency or one of its transitive dependencies is compromised or publishes an unsafe release.
  2. A user follows the installation instructions without a lock file, version constraints, or hash verification.
  3. pip resolves and downloads the current package set.
  4. Package installation or build logic executes with the privileges of the user running the command.
  5. The packages are installed into the system Python environment because package-management safeguards were bypassed.
  6. Malicious code can execute during installation or later when document_reader.py imports and uses the affected dependency.

Impact Assessment

Exploitation can execute code with the privileges of the account performing installation or running the Skill. I ...[truncated 289 chars]

Remediation
View remediation

Remediation Suggestions

  • Install dependencies inside a dedicated virtual environment or isolated container.
  • Remove --break-system-packages from the recommended command.
  • Pin all direct and transitive dependencies to reviewed versions using a lock file.
  • Require cryptographic hashes, for example through a generated requirements file used with pip --require-hashes.
  • Configure installation to use an explicitly trusted package index.
  • Review package provenance, maintenance status, and known vulnerabilities before updating pins.
  • Use automated dependency scanning and controlled update workflows rather than resolving unrestricted latest versions during deployment.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/document_reader.py:111
Finding

Unbounded Document and Archive Processing Enables Resource Exhaustion

Content
View full analysis

Vulnerability Details

File Location: scripts/document_reader.py:111-113, scripts/document_reader.py:223-224, scripts/document_reader.py:269-275, and scripts/document_reader.py:367-369
Vulnerability Type: Unrestricted memory and decompression resource consumption
Risk Level: Medium

Vulnerable Code

Plain-text files are read entirely into memory:

python
def read_text(self, filepath: str) -> str:
    """读取纯文本文件"""
    with open(filepath, 'r', encoding='utf-8', errors='replace') as f:
        return f.read()

ZIP members are also loaded completely:

python
with zf.open(found) as f:
    content_bytes = f.read()

TAR members are extracted and read without a size limit:

python
f = tf.extractfile(found)
if f is None:
    return {
        'success': False,
        'error': f"Cannot extract file '{inner_path}'"
    }
content_bytes = f.read()

The 7-Zip handler reads the selected object completely:

python
extracted = zf.read([inner_path])
content_bytes = extracted[inner_path].read()
extracted[inner_path].close()

Technical Analysis

The reader does not enforce limits on source file size, uncompressed archive member size, compression ratio, parser complexity, elapsed processing time, memory use, or CPU use. Multiple paths call read() without a maximum byte count and retain the resulting bytes or text in memory.

A small compressed input may expand into a much larger member. After expansion, the content is additionally written to a temporary file and passed to document-processing libraries, which may allocate further memory or perform expensive parsing. The output is also accumulated as a complete string. The message claiming that content is truncated only appears after the complete content has already been loaded, parsed, stored, and printed, so it does not provide a resource limit.

Attack Path

  1. An attacker supplies an oversized ...[truncated 1086 chars]
Remediation
View remediation

Remediation Suggestions

  • Reject input files and archive members whose declared or measured sizes exceed a documented limit.
  • Validate uncompressed member sizes and compression ratios before extraction where metadata is available.
  • Read archive content incrementally in bounded chunks rather than calling unrestricted read().
  • Stop processing immediately once the configured byte or character limit is reached.
  • Limit output accumulation and avoid constructing complete workbook, presentation, or extracted-text output in memory.
  • Execute complex document parsers in isolated worker processes with CPU, memory, file-size, and execution-time limits.
  • Apply temporary-storage quotas and verify available capacity before writing extracted data.
  • Treat archive metadata as untrusted and account for inaccurate declared sizes by enforcing limits while streaming.
  • Return a controlled error when any size, ratio, timeout, or resource threshold is exceeded.
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 (7)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill advertises and demonstrates local file-reading capability, including arbitrary document paths and archive contents, but does not declare any explicit tool scope such as permissions or allowed-tools. This creates an authorization ambiguity where a consuming agent or user may not realize the skill can access sensitive local files, increasing the chance of unintended data exposure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill is designed to read local documents and files inside archives, which can easily include confidential material such as reports, credentials, source code, or personal data. Without a prominent warning about sensitive local content, users may invoke it on private files without understanding the privacy and data-handling risk.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The archive-reading functions extract attacker-controlled content to a predictable path under /tmp before parsing it. Using a fixed, guessable temporary filename can enable symlink or race-condition attacks in multi-user environments, and it also violates the claimed 'direct' read-only behavior by performing filesystem writes.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

A read-only document reader should not need to create predictable files in /tmp, especially from untrusted archive contents. This creates unnecessary write capability and can be abused for file clobbering, symlink attacks, information disclosure through temp-file reuse, or interference between concurrent runs.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The manifest description and primary usage text are presented in Chinese, but the skill does not indicate that language is optional or provide a locale choice. This can amount to a language policy issue when a specific language is implicitly enforced without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This code includes natural-language content in Chinese, beginning with comments such as '尝试导入各种文档处理库', while the CLI description and behavior do not indicate that the skill is intentionally region-specific or provide a language/locale option. Under the policy rule, forcing a specific language without opt-in can be a locale-policy issue.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The manifest presents the skill as a universal document reader for formats like PDF, DOCX, XLSX, PPTX, RTF, and ODT, plus archive-contained documents. The implementation additionally treats many generic text and source formats such as js, py, sh, and bat as supported readable targets, which is broader than the stated document-oriented scope.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.