Back to skill

Security audit

Word Comments Extractor

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed local Word comment extractor with some ordinary security hardening gaps, but no evidence of hidden access, exfiltration, persistence, or destructive behavior.

Install only in an isolated Python environment, pin pywin32 if possible, and avoid running the extractor on DOCX files from untrusted sources until archive size and member validation are added.

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
extract_comments.py:32
Finding

Unbounded Extraction of an Untrusted DOCX Archive

Content
View full analysis

Vulnerability Details

File Location: extract_comments.py:32-33
Vulnerability Type: Unrestricted archive extraction
Risk Level: Medium

Vulnerable Code

python
with zipfile.ZipFile(docx_path, 'r') as zf:
    zf.extractall(output_dir)

Technical Analysis

The skill treats a user-supplied DOCX file as a ZIP archive and extracts every member without enforcing limits on:

  • The number of archive members
  • The compressed or uncompressed size of each member
  • The total expanded size
  • Compression ratios
  • Extraction duration
  • The set of files required by the application

The code validates only that the supplied file is recognized as a ZIP archive. A malicious document can therefore contain a ZIP bomb or a large number of entries. Calling extractall() on such an archive can consume substantial disk space, CPU time, and I/O resources.

Although modern supported Python versions perform path sanitization in ZipFile.extractall(), the implementation should still explicitly validate member paths and reject symbolic-link-like or otherwise unexpected entries as a defense-in-depth measure.

Attack Path

  1. An attacker creates a DOCX-compatible ZIP archive containing highly compressed data, oversized members, or an excessive number of entries.
  2. The attacker provides the crafted document to a user or workflow that invokes this skill.
  3. zipfile.is_zipfile() accepts the file because it has a valid ZIP structure.
  4. zf.extractall(output_dir) expands every archive member into the temporary directory.
  5. Extraction consumes local disk space, CPU time, and I/O capacity until the process fails or the host becomes resource constrained.
  6. The temporary directory is removed in a finally block when possible, but this does not prevent resource exhaustion during extraction and may not recover space promptly if the process or host is forcibly terminated.

Impact Assessment

Successful exploitation can cause a local denial of service in ...[truncated 339 chars]

Remediation
View remediation

Remediation Suggestions

Avoid extracting the entire archive. Read only the two required members, word/comments.xml and word/document.xml, and enforce explicit limits before and during processing.

Recommended controls include:

  1. Inspect every relevant ZipInfo object before reading or extracting it.
  2. Reject archives exceeding an approved member-count limit.
  3. Enforce maximum compressed and uncompressed sizes per member.
  4. Enforce a maximum cumulative uncompressed size.
  5. Reject suspicious compression ratios and encrypted entries.
  6. Normalize and validate member paths to ensure they remain inside the intended temporary directory.
  7. Reject unexpected link-like entries and non-regular files.
  8. Parse XML incrementally or enforce XML input-size limits.
  9. Apply execution time, disk quota, and memory limits at the process or sandbox level.

A safer design is:

python
required_members = {
    "word/comments.xml",
    "word/document.xml",
}

with zipfile.ZipFile(docx_path, "r") as zf:
    infos = {info.filename: info for info in zf.infolist()}

    for name in required_members:
        info = infos.get(name)
        if info is None:
            raise ValueError(f"Required DOCX member is missing: {name}")
        if info.file_size > MAX_XML_SIZE:
            raise ValueError(f"DOCX member is too large: {name}")
        if info.compress_size == 0 and info.file_size > 0:
            raise ValueError(f"Suspicious compressed member: {name}")
        if info.compress_size and info.file_size / info.compress_size > MAX_RATIO:
            raise ValueError(f"Suspicious compression ratio: {name}")

        target = os.path.abspath(os.path.join(output_dir, name))
        root = os.path.abspath(output_dir) + os.sep
        if not target.startswith(root):
            raise ValueError(f"Unsafe archive path: {name}")

        os.makedirs(os.path.dirname(target), exist_ok=True)
        with zf.open(info) as src, open(target, "wb") as dst:
            shutil.copyfileobj
...[truncated 157 chars]

T08 · Insecure Dependencies

Note
Location
SKILL.md:8
Finding

Unpinned Third-Party Dependency Installation

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:8
Vulnerability Type: Unpinned dependency installation
Risk Level: Low

Vulnerable Code

yaml
install:
  steps:
    - description: "Install pywin32 Python package"
      command: "python -m pip install pywin32"

Technical Analysis

The installation instruction resolves and installs the latest available pywin32 release from the Python package index configured in the user's environment. It does not specify an audited version, verify artifact hashes, use a lock file, or explicitly constrain the package source.

This creates a mutable and non-reproducible supply-chain boundary. The package installed during one deployment may differ from the package reviewed or installed during another deployment. Risk arises if the configured index, mirror, account, DNS path, or future dependency release is compromised. A malicious package artifact can execute code during installation or when imported by the skill.

No evidence in the audited project indicates that pywin32 itself is malicious. The finding concerns the unsafe dependency-resolution practice rather than a confirmed malicious package.

Attack Path

  1. A user follows the documented installation command.
  2. pip queries the package index or mirror configured in that environment.
  3. The command accepts whichever pywin32 release currently satisfies the unconstrained package name.
  4. If the repository, mirror, publisher account, local pip configuration, or selected artifact has been compromised, pip downloads the attacker-controlled package.
  5. Malicious package logic executes during installation or later when win32com.client is imported.
  6. The malicious code runs with the same operating-system privileges and network/file access as the Python or agent process.

Impact Assessment

A compromised dependency could execute arbitrary code with the privileges of the user installing or running the skill. This could permit access to fil ...[truncated 476 chars]

Remediation
View remediation

Remediation Suggestions

Use a reviewed, fixed dependency version and verify the exact distribution artifact. Recommended measures include:

  1. Pin pywin32 to a specific audited version.
  2. Record approved hashes in a requirements or lock file.
  3. Install with --require-hashes.
  4. Use an explicitly trusted package index.
  5. Review and update the pinned dependency through a controlled maintenance process.
  6. Run dependency vulnerability and provenance checks in CI.
  7. Install into an isolated virtual environment under a non-privileged account.

For example:

text
# requirements.txt
pywin32==<audited-version> \
    --hash=sha256:<approved-wheel-hash>

Install it with:

bash
python -m pip install \
  --index-url https://pypi.org/simple \
  --require-hashes \
  -r requirements.txt

Because pywin32 publishes platform- and interpreter-specific wheels, include the approved hash for every supported artifact or maintain platform-specific lock files.

Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (2)

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest describes extracting comments from Word documents and formatting them into review opinions, which is largely consistent with parsing document contents. However, this function launches and controls a local Word application through COM to open the document and inspect comment metadata, introducing a broader desktop-automation capability than a typical extractor requires.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The manifest includes several Chinese-only keywords related to the skill's operation, but there is no accompanying description that the skill is intended specifically for Chinese-language users or that language selection is optional. This can create a locale expectation or discovery bias without explicit user opt-in or justification.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.