Back to skill

Security audit

docx-md

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent DOCX review utility that clearly discloses local document reading, editing, and finalization, though users should handle sensitive documents and final outputs carefully.

Install only in an isolated Python environment, use pinned dependencies if possible, and run it on copies of documents. Do not send confidential contracts or business documents to an external LLM unless that provider is approved for the data, and treat finalize as a deliberate cleanup step that removes review metadata from the output file.

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/read_docx.py:195
Finding

Unhardened XML Parsing and Unbounded DOCX Archive Processing

Content
View full analysis
list[dict[str, Any]]: try: data = zipf.read("word/comments.xml") except KeyError: return [] root = etree.fromstring(data) out = [] for c in root.findall(f".//{{{W_NS}}}comment"): out.append({ "id": _attr(c, "id"), "author": _attr(c, "author"), "date": _attr(c, "date"), "text": _text(c).strip(), }) return out def read_docx(path: str | Path) -> dict[str, Any]: """Read docx and return standard structure: { body, comments, path }. Body blocks have type, segments, blockIndex.""" path = Path(path) if not path.exists(): return {"error": f"File not found: {path}"} try: with zipfile.ZipFile(path, "r") as z: doc = z.read("word/document.xml") comments = _parse_comments(z) except Exception as e: return {"error": str(e)} root = etree.fromstring(doc) ``` `scripts/apply_edits_docx.py:410-419`: ```python with zipfile.ZipFile(docx_path, "r") as z_in: doc_bytes = z_in.read("word/document.xml") try: comments_bytes = z_in.read("word/comments.xml") comments_root = etree.fromstring(comments_bytes) except KeyError: comments_root = None comments_bytes = None doc_root = etree.fromstring(doc_bytes) ``` ### Technical Analysis DOCX files are ZIP archives containing XML resources. Both scripts treat the DOCX as potentially arbitrary input, load selected archive members entirely into memory with `ZipFile.read()`, and then parse those bytes through `etree.fromstring()` without explicitly ...[truncated 2389 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Mutable and Unhashed Third-Party Dependency Resolution

Content
View full analysis
=4.9.0 docx-revisions>=0.1.3 ``` `SKILL.md:71`: ```markdown **Requires**: `pip install docx-revisions` (see `requirements.txt`) ``` `README.md:113`: ```markdown - `lxml`: `pip install lxml` ``` ### Technical Analysis The dependency file specifies only minimum versions, while the documentation recommends installing packages by name without a fixed version or package hash. Each installation can therefore resolve to a different future release. This creates a mutable supply-chain boundary: the audited source does not determine which dependency code will execute. A compromised upstream release, compromised package-publishing account, unsafe package-index configuration, or unreviewed incompatible release could be selected automatically. The package names themselves are consistent between the source and documentation, and the audit found no evidence of typosquatting or an intentionally malicious dependency. The weakness is the absence of reproducible version and integrity controls. ### Attack Path 1. A user follows the documented installation command or installs from `requirements.txt`. 2. The package resolver queries the configured Python package index. 3. Because only lower bounds or no versions are specified, the resolver selects the latest compatible releases available at installation time. 4. If a selected release or configured index has been compromised, malicious package code can execute during installation, import, or normal Skill operation. 5. The dependency code runs with the same filesystem and process privileges as the user or service executing the installation and Skill. ### Impact Assessment A compromised dependency could execute arbitrary Python code w ...[truncated 435 chars]
Remediation
View remediation
docx-revisions== ``` 2. Generate and verify cryptographic hashes for all direct and transitive dependencies. Install with: ```bash python -m pip install --require-hashes -r requirements.txt ``` 3. Maintain a lock file generated by a dependency-management tool such as `pip-tools`, including resolved transitive dependencies and hashes. 4. Configure installation to use a trusted, explicitly selected package index. Avoid untrusted extra indexes that can introduce dependency-confusion risk. 5. Perform routine vulnerability and provenance review of locked releases before updating them. 6. Update `README.md` and `SKILL.md` so installation examples use the reviewed lock or requirements file rather than unversioned package-name commands. 7. Execute dependency installation in an isolated virtual environment and avoid installing packages with elevated system privileges. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (15)

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

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

md
| Goal | Action |
|------|--------|
| **Get document for AI** | **Read**: run read script → Markdown (default) or JSON. Markdown includes `<!-- b:N -->` blockIndex markers for edit targeting. |
| **Apply AI edits to docx** | **Modify**: run apply script with docx + edits JSON → new docx with track changes and comments. |
| **Deliver final version** | **Finalize**: run finalize script → new docx with no revisions/comments. |

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The finalize guidance explicitly describes irreversible operations: accepting all revisions and removing all comments, which can permanently discard audit history, reviewer annotations, and recoverable context. In a document-review skill that directly modifies DOCX files, lack of any warning, confirmation, or backup expectation increases the chance of accidental or silent destruction of important document metadata.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README explicitly advertises operations that modify DOCX files and a finalize step that accepts revisions and removes comments, but it does not warn users that these actions can irreversibly alter source documents or erase review metadata. In a document-review workflow, this omission increases the risk of accidental destruction of audit trails, comments, and tracked changes if users run the commands on original files or misunderstand the semantics of finalize.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill documentation describes scripts that read and write local files, including modifying and finalizing DOCX documents, but the manifest declares no explicit tool scope such as permissions or allowed-tools. This creates an overly broad and implicit capability boundary, which can allow downstream agents to invoke file operations without clear least-privilege constraints or policy review.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The document explicitly recommends sending long DOCX content such as contracts to an LLM, but provides no warning about privacy, confidentiality, or data-handling risks. In a document-review skill, this omission can lead users to transmit sensitive legal or business content to external model providers without understanding retention, logging, or cross-border processing implications.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This markdown states that the program converts edit JSON to OOXML and writes back to the DOCX, which can alter user documents. The description does not include any warning about overwriting files, preserving backups, or confirming potentially destructive edits.

Content

No source excerpt is available for this finding.

Tainted flow: 'cleaned' from pathlib.Path.read_bytes (line 69, file read) → pathlib.Path.write_bytes (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/finalize_docx.py (reported line 70)May include surrounding context.

python
# Step 2: remove comment markup via regex on raw bytes
        cleaned = _remove_comments_raw(tmp_path.read_bytes())
        out_path.write_bytes(cleaned)
    finally:
        tmp_path.unlink(missing_ok=True)

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 · scripts/read_docx.py (reported line 318)May include surrounding context.

python
args = ap.parse_args()
    out = read_docx(args.docx)
    if "error" in out:
        print(json.dumps(out, ensure_ascii=False), file=__import__("sys").stderr)
        __import__("sys").exit(1)

    if args.format == "json":

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 · scripts/read_docx.py (reported line 319)May include surrounding context.

python
out = read_docx(args.docx)
    if "error" in out:
        print(json.dumps(out, ensure_ascii=False), file=__import__("sys").stderr)
        __import__("sys").exit(1)

    if args.format == "json":
        s = json.dumps(out, ensure_ascii=False, indent=2)

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

Line L75 uses Chinese field values ("原文本", "修改后文本", "修改依据") as the sole example, which can imply a language-specific workflow. The file does not state that the skill is region-specific or that users may choose their preferred language or locale.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency is specified with only a lower bound, so builds may resolve to different versions over time and pull in unexpected or vulnerable releases. In a document-processing skill, this increases supply-chain and reproducibility risk because parsing untrusted .docx/XML content depends on a native/complex library with a history of security issues.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
lxml>=4.9.0
docx-revisions>=0.1.3

Unverifiable Dependency: lxml has 14 known advisory(ies) (CVE-2021-43818 (lxml's HTML Cleaner allows crafted and SVG embedded scripts to pass through); CVE-2014-3146 (lxml Cross-site Scripting Via Control Characters); CVE-2021-28957 (lxml vulnerable to Cross-Site Scripting ) +11 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
91% confidence
Finding

lxml has multiple historical advisories, and because the manifest does not pin an exact version, it is impossible to verify from this file alone whether deployment will use a fixed or vulnerable release. This is more concerning in a low-level document conversion tool because lxml processes attacker-controlled document/XML structures, so vulnerable parser-related behavior could be reachable depending on usage.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
89% confidence
Finding

The docx-revisions package is also unpinned, which means installs are not reproducible and could silently pick up a compromised or breaking release. Because this skill reads and writes .docx files with revision handling, trust in dependency integrity matters and supply-chain tampering could affect document contents or processing behavior.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
lxml>=4.9.0
docx-revisions>=0.1.3

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The docstring for _flatten_paragraph_content says comment nodes are skipped for accept_revision, which is true only for paragraph anchors in document.xml. However, the overall accept flow in this file does not remove corresponding comment entries from comments.xml, so comments are not actually removed from the document package as the broader behavior implies.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest describes three operations, including a separate finalize capability that accepts revisions and removes comments. In this file, the CLI presents itself only as applying contract-review edits, yet the implementation also supports an "accept_revision" operation that finalizes tracked changes for a paragraph.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.