Back to skill

Security audit

docx-to-md

Security checks for vulnerabilities and agentic risk

Overview

This skill is a straightforward DOCX-to-Markdown converter that writes converted Markdown and extracted images locally, with some ordinary file-handling cautions but no evidence of hidden, persistent, network, credential, or destructive behavior.

Install only if you are comfortable with a local converter that writes Markdown and image files to disk. Use a new or empty output folder, avoid running it on untrusted or very large DOCX files, and note that the user-facing documentation and messages are in Chinese.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/docx_to_md.py:28
Finding

Unbounded DOCX Archive Extraction Enables Resource Exhaustion

Content
View full analysis

Vulnerability Details

File Location: scripts/docx_to_md.py, lines 28–41
Vulnerability Type: Unbounded archive extraction and processing
Risk Level: Medium

Vulnerable Code

python
image_files = []
with zipfile.ZipFile(doc_path, 'r') as zip_ref:
    media_files = [f for f in zip_ref.namelist() if f.startswith('word/media/') and not f.endswith('/')]
    for i, img_file in enumerate(media_files):
        ext = os.path.splitext(img_file)[1]
        img_name = f"image_{i+1}{ext}"
        zip_ref.extract(img_file, output_dir)
        old_path = os.path.join(output_dir, img_file)
        new_path = os.path.join(output_dir, img_name)
        if os.path.exists(old_path):
            os.rename(old_path, new_path)
            image_files.append(img_name)

Technical Analysis

A DOCX file is a ZIP archive. The converter extracts every non-directory archive member under word/media/ without validating:

  • The number of media members.
  • The uncompressed size of each member.
  • The cumulative uncompressed size.
  • The compression ratio.
  • Available disk space or processing limits.

Calling ZipFile.extract() on every matching member permits a crafted DOCX containing numerous files or highly compressed, oversized media to consume excessive disk space and CPU. The file is subsequently processed by python-docx, which can add further memory and CPU consumption.

This is an insecure resource-management flaw in code that processes attacker-supplied archives.

Attack Path

  1. An attacker creates a syntactically valid DOCX archive containing many media members or highly compressible, very large content under word/media/.
  2. The attacker provides the DOCX to a user or service that invokes this Skill.
  3. The converter enumerates every matching member without enforcing size or count limits.
  4. zip_ref.extract() decompresses all selected members into the output directory.
  5. Disk, CP ...[truncated 480 chars]
Remediation
View remediation

Remediation Suggestions

  • Inspect each ZipInfo entry before extraction and enforce a conservative maximum uncompressed size per member.
  • Enforce limits on the total number of media members and their cumulative uncompressed size.
  • Reject entries whose compression ratio exceeds a safe threshold.
  • Stream each file in bounded chunks rather than using unrestricted ZipFile.extract().
  • Abort extraction cleanly when any configured limit is exceeded and delete partial output.
  • Apply process-level CPU, memory, execution-time, and disk quotas when handling untrusted documents.
  • Validate that the input is a supported DOCX package before performing expensive processing.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/docx_to_md.py:25
Finding

Predictable Output Names Permit Existing File Overwrites

Content
View full analysis

Vulnerability Details

File Location: scripts/docx_to_md.py, lines 25–41 and 108–110
Vulnerability Type: Unsafe output-file collision handling
Risk Level: Low

Vulnerable Code

python
os.makedirs(output_dir, exist_ok=True)

image_files = []
with zipfile.ZipFile(doc_path, 'r') as zip_ref:
    media_files = [f for f in zip_ref.namelist() if f.startswith('word/media/') and not f.endswith('/')]
    for i, img_file in enumerate(media_files):
        ext = os.path.splitext(img_file)[1]
        img_name = f"image_{i+1}{ext}"
        zip_ref.extract(img_file, output_dir)
        old_path = os.path.join(output_dir, img_file)
        new_path = os.path.join(output_dir, img_name)
        if os.path.exists(old_path):
            os.rename(old_path, new_path)
            image_files.append(img_name)

md_path = os.path.join(output_dir, f'{doc_title}.md')
with open(md_path, 'w', encoding='utf-8') as f:
    f.write(''.join(md_content))

Technical Analysis

The converter accepts an existing output directory and generates predictable destination names such as image_1.png and a Markdown filename derived from the input document name. It does not check whether these destination files already exist.

Opening the Markdown destination in w mode unconditionally truncates an existing file. On platforms where os.rename() replaces an existing destination, extracted images can also overwrite existing files. On platforms that reject such collisions, conversion may instead fail partway through and leave partial output.

The attack requires the victim to select or implicitly use an output directory containing colliding filenames. The affected scope is limited to predictable destination paths created by the converter in that directory.

Attack Path

  1. A target output directory already contains a file whose name matches the generated Markdown filename or a predictable image name such as `image_1.png ...[truncated 783 chars]
Remediation
View remediation

Remediation Suggestions

  • Require the output directory to be new or empty by default.
  • Check every destination for an existing file before writing or renaming.
  • Use exclusive file creation, such as mode x, for the Markdown output.
  • Generate collision-resistant image names or create a unique per-conversion output directory.
  • Add an explicit --overwrite option if replacement behavior is required, and clearly warn users before overwriting data.
  • Use atomic file creation and replacement procedures to avoid partial outputs.
  • On any collision or conversion failure, stop safely and clean up files created during the current operation.
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill documents code that writes Markdown files and extracted images to disk, but it does not declare any tool scope such as permissions or allowed-tools. This weakens least-privilege controls and can cause the skill to be executed with broader file-write capability than users or orchestrators expect.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

SQP-3 applies to all file types and covers language/locale policy violations. The file presents the description and all user instructions only in Chinese, with no opt-in, alternative language, or statement that the skill is intended exclusively for a Chinese-speaking audience.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The skill explains that it converts documents and extracts images, but it does not clearly warn that running it will create output directories and write multiple files to disk. This can lead to unintended local file creation, workspace clutter, or accidental overwrites if users assume the operation is read-only.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code includes multiple user-facing strings such as error messages, status output, and the argparse description only in Chinese. That creates a locale/language policy issue because the skill forces a specific language without any user opt-in or alternative.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.