Back to skill

Security audit

Docx Anthropic

Security checks for vulnerabilities and agentic risk

Overview

This Word document skill is mostly on-purpose but needs review because it includes unsafe LibreOffice execution paths, persistent macros, broader Office-file handling than advertised, and unpinned global dependency installation.

Install only if you are comfortable running document-processing code in an isolated environment. Avoid using it on untrusted Office files until archive extraction limits, XML escaping, the LibreOffice macro profile, and the LD_PRELOAD shim are fixed. Prefer local pinned dependencies over the documented global npm install, and explicitly set comment/tracked-change author names before producing documents for others.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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
Findings (6)

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/office/soffice.py:24
Finding

Predictable LD_PRELOAD Library Allows Local Tool Hijacking

Content
View full analysis
dict: env = os.environ.copy() env["SAL_USE_VCLPLUGIN"] = "svp" if _needs_shim(): shim = _ensure_shim() env["LD_PRELOAD"] = str(shim) return env ``` ```python _SHIM_SO = Path(tempfile.gettempdir()) / "lo_socket_shim.so" ``` ```python def _ensure_shim() -> Path: if _SHIM_SO.exists(): return _SHIM_SO src = Path(tempfile.gettempdir()) / "lo_socket_shim.c" src.write_text(_SHIM_SOURCE) subprocess.run( ["gcc", "-shared", "-fPIC", "-o", str(_SHIM_SO), str(src), "-ldl"], check=True, capture_output=True, ) src.unlink() return _SHIM_SO ``` ### Technical Analysis The code creates or reuses a shared object at the globally predictable path `/tmp/lo_socket_shim.so`. If that path already exists, the code accepts it without verifying its ownership, permissions, file type, integrity, or contents. When Unix-domain sockets are unavailable, the existing file is assigned to `LD_PRELOAD`. The operating system loader will consequently load that library into the LibreOffice process before normal libraries. A malicious shared object can execute arbitrary native code through a constructor function as soon as LibreOffice starts. The source file `/tmp/lo_socket_shim.c` and compiler output are also predictable, introducing race conditions and symlink-replacement opportunities. ### Attack Path 1. A local attacker with access to the shared temporary directory creates `/tmp/lo_socket_shim.so` containing malicious native code. 2. The Skill runs in an environment where `_needs_shim()` returns `True`. 3. `_ensure_shim()` observes that the predictable file exists and returns it without validation. 4. `get_soffice_env()` sets `LD_PRELOAD` to the att ...[truncated 635 chars]
Remediation
View remediation

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/accept_changes.py:14
Finding

Predictable Persistent LibreOffice Profile Allows Macro Hijacking

Content
View full analysis
bool: macro_dir = Path(MACRO_DIR) macro_file = macro_dir / "Module1.xba" if macro_file.exists() and "AcceptAllTrackedChanges" in macro_file.read_text(): return True if not macro_dir.exists(): subprocess.run( [ "soffice", "--headless", f"-env:UserInstallation=file://{LIBREOFFICE_PROFILE}", "--terminate_after_init", ], capture_output=True, timeout=10, check=False, env=get_soffice_env(), ) macro_dir.mkdir(parents=True, exist_ok=True) try: macro_file.write_text(ACCEPT_CHANGES_MACRO) return True except Exception as e: logger.warning(f"Failed to setup LibreOffice macro: {e}") return False ``` ### Technical Analysis The LibreOffice profile and macro use fixed paths beneath `/tmp`. The profile is retained between runs and is not isolated to the current process. If `Module1.xba` already exists, the implementation trusts it whenever its text contains the string `AcceptAllTrackedChanges`. It does not verify that the file exactly matches the expected macro, nor does it validate ownership, permissions, symlink status, or directory ancestry. A malicious macro can therefore include the expe ...[truncated 1199 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/comment.py:34
Finding

Unescaped Comment Fields Permit OOXML Injection

Content
View full analysis
{text} """ ``` ```python def _append_xml(xml_path: Path, root_tag: str, content: str) -> None: dom = defusedxml.minidom.parseString(xml_path.read_text(encoding="utf-8")) root = dom.getElementsByTagName(root_tag)[0] ns_attrs = " ".join(f'xmlns:{k}="{v}"' for k, v in NS.items()) wrapper_dom = defusedxml.minidom.parseString(f"{content}") for child in wrapper_dom.documentElement.childNodes: if child.nodeType == child.ELEMENT_NODE: root.appendChild(dom.importNode(child, True)) output = _encode_smart_quotes(dom.toxml(encoding="UTF-8").decode("utf-8")) xml_path.write_text(output, encoding="utf-8") ``` ```python _append_xml( comments, "w:comments", COMMENT_XML.format( id=comment_id, author=author, date=ts, initials=initials, para_id=para_id, text=text, ), ) ``` ### Technical Analysis The `author`, `initials`, and `text` values are interpolated directly into XML source. The author and initials values are inserted into attributes without XML escaping. The comment text is intentionally accepted as pre-escaped XML and is inserted into an element before parsing. An attacker can supply quotes and XML delimiters that terminate the intended attribute or element and introduce additional OOXML nodes. ...[truncated 1009 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/office/unpack.py:51
Finding

Unbounded Office Archive Extraction Enables Resource Exhaustion

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:58
Finding

Unpinned Global npm Installation Creates Supply-Chain Exposure

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/accept_changes.py:68
Finding

LibreOffice Timeout Is Incorrectly Reported as Successful Sanitization

Content
View full analysis
{output_file}", ) ``` ### Technical Analysis A timeout does not demonstrate that LibreOffice completed the macro, saved the output, or closed the document. Nevertheless, the exception handler unconditionally returns a success message. No subsequent validation checks whether the output is a valid DOCX or whether tracked-change elements remain. The function therefore fails open during an uncertain conversion state. ### Attack Path 1. An attacker supplies a malformed, unusually complex, or resource-intensive DOCX file. 2. LibreOffice fails to complete within the 30-second timeout. 3. `subprocess.TimeoutExpired` is raised. 4. The function reports that all tracked changes were successfully accepted. 5. The user treats the copied or partially modified output as sanitized. 6. Hidden revisions, deleted text, comments, or other revision history may remain in the document. ### Impact Assessment The issue can cause disclosure of revision history or deleted content when users rely on the success message before distributing a document. It can also result in use of a partially written or corrupted output file. It does not grant additional operating-system privileges. ]]>
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (34)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill includes package-level XML validation/repair and references broader OOXML handling than its Word-only description suggests. In an agent setting, understated low-level repair/manipulation capability can make document processing more dangerous because the agent may be routed into operations that alter internal package structure or touch unexpected file types.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The skill includes package-level XML validation/repair and references broader OOXML handling than its Word-only description suggests. In an agent setting, understated low-level repair/manipulation capability can make document processing more dangerous because the agent may be routed into operations that alter internal package structure or touch unexpected file types.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill includes package-level XML validation/repair and references broader OOXML handling than its Word-only description suggests. In an agent setting, understated low-level repair/manipulation capability can make document processing more dangerous because the agent may be routed into operations that alter internal package structure or touch unexpected file types.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill includes package-level XML validation/repair and references broader OOXML handling than its Word-only description suggests. In an agent setting, understated low-level repair/manipulation capability can make document processing more dangerous because the agent may be routed into operations that alter internal package structure or touch unexpected file types.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill includes package-level XML validation/repair and references broader OOXML handling than its Word-only description suggests. In an agent setting, understated low-level repair/manipulation capability can make document processing more dangerous because the agent may be routed into operations that alter internal package structure or touch unexpected file types.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill includes package-level XML validation/repair and references broader OOXML handling than its Word-only description suggests. In an agent setting, understated low-level repair/manipulation capability can make document processing more dangerous because the agent may be routed into operations that alter internal package structure or touch unexpected file types.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill includes package-level XML validation/repair and references broader OOXML handling than its Word-only description suggests. In an agent setting, understated low-level repair/manipulation capability can make document processing more dangerous because the agent may be routed into operations that alter internal package structure or touch unexpected file types.

Content

No source excerpt is available for this finding.

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 418)May include surrounding context.

CRITICAL: Use smart quotes for new content. When adding text with apostrophes or quotes, use XML entities to produce smart quotes:

xml
<!-- Use these entities for professional typography -->
<w:t>Here&#x2019;s a quote: &#x201C;Hello&#x201D;</w:t>

| Entity | Character |

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 499)May include surrounding context.

xml
<w:p>
  <w:pPr>
    <w:numPr>...</w:numPr>  <!-- list numbering if present -->
    <w:rPr>
      <w:del w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z"/>
    </w:rPr>

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/office/soffice.py (reported line 25)May include surrounding context.

python
def get_soffice_env() -> dict:
    env = os.environ.copy()
    env["SAL_USE_VCLPLUGIN"] = "svp"

    if _needs_shim():

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Compiling and injecting a native LD_PRELOAD shim gives the skill the ability to alter process behavior at the libc boundary, which is an extremely sensitive capability unrelated to ordinary document manipulation. In the context of a DOCX skill, this is especially dangerous because it can subvert sandboxing assumptions and execute arbitrary native code under the guise of file conversion.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The manifest describes a skill for creating, reading, editing, and manipulating Word .docx documents, but this file implements validation logic for PowerPoint PresentationML/PPTX content, including slide layouts, notes slides, and presentation relationships. That behavior is outside the manifest's declared document type and operational scope, indicating the skill contains functionality for a different Office format than it claims.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill documents use of shell commands, file reads/writes, and likely environment-dependent tooling, but it declares no explicit tool scope or permissions boundary. This increases the chance of over-privileged execution, unintended command/file access, and poor policy enforcement when the skill is invoked.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger text includes very generic terms like report, memo, letter, and template, which can cause the skill to activate for ordinary writing tasks unrelated to DOCX manipulation. Overbroad invocation raises the chance that shell/file-capable workflows are selected unnecessarily, expanding attack surface and enabling unintended document or filesystem operations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill instructs the agent to use a fixed author identity ('Claude') for tracked changes and comments unless the user says otherwise. This can create inaccurate attribution in generated documents, misrepresent authorship, and leak the agent/vendor identity into user artifacts without consent.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/accept_changes.py (reported line 68)May include surrounding context.

python
]

    try:
        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

On timeout, the function reports successful acceptance of tracked changes even though LibreOffice did not complete and the document state is unknown. In an agent workflow, this can cause downstream systems or users to trust a document as sanitized or finalized when sensitive edits, comments, or tracked changes may still remain.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/accept_changes.py (reported line 99)May include surrounding context.

python
return True

    if not macro_dir.exists():
        subprocess.run(
            [
                "soffice",
                "--headless",

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code overwrites word/document.xml in place after removing proofing markers, stripping revision metadata, and merging runs. Although the module docstring describes the behavior, there is no user-facing confirmation, logging, or explicit warning near the destructive file write, so callers may not realize the source document XML is being modified irreversibly.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The function rewrites word/document.xml in place after simplifying tracked changes, which alters the document's revision history without any explicit user-facing disclosure, confirmation, or creation of a separate output copy. In a document-processing skill, this is security-relevant because tracked changes can contain legal, audit, or authorship evidence, and silent mutation of that data can mislead users or destroy provenance unexpectedly.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

Running soffice itself may be expected for DOCX handling, but this module also depends on external toolchain execution through subprocess invocation of gcc to build a shim. A document skill description does not justify compiling native code or relying on a compiler toolchain at runtime.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/office/soffice.py (reported line 37)May include surrounding context.

python
def run_soffice(args: list[str], **kwargs) -> subprocess.CompletedProcess:
    env = get_soffice_env()
    return subprocess.run(["soffice"] + args, env=env, **kwargs)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
97% confidence
Finding

The code writes C source into a world-writable temp directory and compiles it into a shared object that is later injected with LD_PRELOAD. This creates a powerful native-code execution path and introduces race/symlink and binary-trust risks that are far beyond normal DOCX handling needs.

Content

Scanner excerpt · scripts/office/soffice.py (reported line 59)May include surrounding context.

python
src = Path(tempfile.gettempdir()) / "lo_socket_shim.c"
    src.write_text(_SHIM_SOURCE)
    subprocess.run(
        ["gcc", "-shared", "-fPIC", "-o", str(_SHIM_SO), str(src), "-ldl"],
        check=True,
        capture_output=True,

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring advertises unpacking DOCX, PPTX, and XLSX, which conflicts with the skill's declared Word-only purpose. Advertising broader capability than the manifest permits makes it more likely the agent or maintainers will use the skill outside its approved scope, undermining security boundaries and review assumptions.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill manifest scopes this capability to Word documents, but the implementation explicitly accepts .pptx and .xlsx files. This scope mismatch can cause the agent to process file types outside the declared trust boundary, increasing the chance of unintended access, misuse, or policy bypass when the skill is selected for document-handling tasks.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.