Back to skill

Security audit

Docx

Security checks for vulnerabilities and agentic risk

Overview

The skill is mainly for Word document editing, but it includes under-disclosed LibreOffice macro execution, native-code shimming, and global dependency installation that users should review carefully.

Install only if you are comfortable with a document skill that can run LibreOffice, execute a macro to accept tracked changes, compile/load a native compatibility shim, and modify Office XML. Prefer running it in an isolated environment, avoid sensitive or untrusted Office files, pin dependencies locally instead of using global npm installs, and treat the `/tmp` shim/profile behavior as something to fix before use on shared systems.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T07 · Tool Hijacking and Spoofing

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

Predictable LD_PRELOAD Library Allows Local Native-Code 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 _SHIM_SO = Path(tempfile.gettempdir()) / "lo_socket_shim.so" def _needs_shim() -> bool: try: s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) s.close() return False except OSError: return True 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 LibreOffice compatibility shim is stored under the fixed path `/tmp/lo_socket_shim.so`. When that path already exists, `_ensure_shim()` accepts the file without validating: - Its owner or permissions - Whether it is a regular file or symbolic link - Whether it was generated from the trusted embedded source - Its cryptographic digest - Whether another process replaced it between validation and use When Unix-domain socket creation is unavailable, the existing file is assigned to `LD_PRELOAD`. The dynamic loader then loads that shared library into the LibreOffice process before normal libraries. An attacker-controlled library can therefore execute arbitrary native code through a constructor or overridden functions. The source path `/tmp/lo_socket_shim.c` is also predictable and written without exclusive creation, creating additional symlink and race-condition exposure. ### Attack Path 1. A local attacker with write access ...[truncated 1201 chars]
Remediation
View remediation

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/accept_changes.py:13
Finding

Predictable LibreOffice Profile Allows Macro Substitution

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 Skill uses the fixed shared profile `/tmp/libreoffice_docx_profile` and executes a macro from that profile. If `Module1.xba` already exists, the code treats it as trusted whenever its text contains the substring `AcceptAllTrackedChanges`. A substring check does not establish the integrity of the macro. A malicious macro can contain the expected procedure name while executing arbitrary additional Basic or UNO operations. The implementation also does not verify directory owne ...[truncated 1649 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:58
Finding

Unpinned Global npm Package Installation Creates Supply-Chain Risk

Content
View full analysis
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 (35)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

If the skill also supports PPTX/presentation validation as indicated by the static finding, that falls outside the declared DOCX-only scope. Scope creep across Office formats expands attack surface and makes authorization decisions less reliable because the skill can touch content types users did not request.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

If the skill also supports PPTX/presentation validation as indicated by the static finding, that falls outside the declared DOCX-only scope. Scope creep across Office formats expands attack surface and makes authorization decisions less reliable because the skill can touch content types users did not request.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

If the skill also supports PPTX/presentation validation as indicated by the static finding, that falls outside the declared DOCX-only scope. Scope creep across Office formats expands attack surface and makes authorization decisions less reliable because the skill can touch content types users did not request.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

If the skill also supports PPTX/presentation validation as indicated by the static finding, that falls outside the declared DOCX-only scope. Scope creep across Office formats expands attack surface and makes authorization decisions less reliable because the skill can touch content types users did not request.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

If the skill also supports PPTX/presentation validation as indicated by the static finding, that falls outside the declared DOCX-only scope. Scope creep across Office formats expands attack surface and makes authorization decisions less reliable because the skill can touch content types users did not request.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

If the skill also supports PPTX/presentation validation as indicated by the static finding, that falls outside the declared DOCX-only scope. Scope creep across Office formats expands attack surface and makes authorization decisions less reliable because the skill can touch content types users did not request.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

If the skill also supports PPTX/presentation validation as indicated by the static finding, that falls outside the declared DOCX-only scope. Scope creep across Office formats expands attack surface and makes authorization decisions less reliable because the skill can touch content types users did not request.

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

The helper conditionally sets LD_PRELOAD to inject a custom native library into LibreOffice, allowing interception and modification of low-level process behavior. For a .docx manipulation skill, this is an unjustified privilege expansion that increases the blast radius from document conversion to arbitrary native-code influence over a spawned process.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Building C source during execution gives the skill an unnecessary native-code compilation capability that is unrelated to ordinary Word document processing. In this context, the feature meaningfully increases risk because it enables dynamic creation of executable artifacts and facilitates stealthy process tampering.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill invokes shell commands and performs file read/write operations but does not declare any explicit tool scope or allowed-tools boundary. That increases the chance an agent can execute broader filesystem or command operations than users would reasonably expect from a document-manipulation skill, especially because the workflow includes conversion, unpacking, and repacking of office files.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger language is broad enough to match common requests like 'report', 'memo', or 'letter' even when the user has not clearly asked for a DOCX workflow. Over-broad routing is dangerous in this context because the skill has shell and file-modifying behaviors, so it may be invoked unnecessarily for ordinary drafting tasks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The instructions include conversion and file-modifying operations without warning about overwrites, output locations, metadata exposure, or handling of untrusted documents. In a document-processing skill, silent modification/conversion can cause data loss or unsafe processing of attacker-supplied Office files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Directing users to unpack, hand-edit XML, and repack documents without strong warnings about corruption risk, backup requirements, and trust boundaries is unsafe. Because malformed OOXML can break documents and embedded relationships/media can carry sensitive content, this workflow makes accidental damage or unsafe handling substantially more likely.

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,

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
88% confidence
Finding

This code performs a direct file write to the DOCX XML payload, and the module docstring states that it removes rsid attributes and proofErr elements before saving. While the docstring describes the behavior technically, there is no explicit warning that the operation mutates the input file contents and strips metadata, which could matter for users expecting a non-destructive formatting-only cleanup.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code overwrites the existing word/document.xml file in place via write_bytes, which is a file-modifying operation affecting user data. Although the module docstring explains the transformation, there is no user-facing warning, confirmation prompt, or visible disclosure at the point where the write occurs.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

There is a clear mismatch between the declared document-oriented purpose and the implemented behavior, which focuses on socket interception, environment mutation, compilation, and process shimming. Such scope drift is dangerous because it hides high-risk runtime behavior behind a benign-sounding skill description, reducing scrutiny and informed consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Executing LibreOffice with LD_PRELOAD set causes undocumented runtime code injection into the child process. In a document skill, undisclosed injection is especially problematic because users expect content transformation, not hidden alteration of system-level process semantics.

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)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code silently writes C source and a shared object into the temporary directory and compiles them without notifying the user or operator. That lack of transparency is risky because it conceals native-code generation and persistence on disk, making abuse or forensic investigation harder.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
96% confidence
Finding

This code invokes a system compiler at runtime to build a shared object in a world-writable temporary directory, which materially expands the skill's capabilities beyond document handling. Even without shell injection, compiling and loading native code creates a powerful execution path that can be abused through temp-file races, binary replacement, or by turning a document skill into a process-manipulation primitive.

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,

Static analysis

No suspicious patterns detected.