Back to skill

Security audit

lhx111

Security checks for vulnerabilities and agentic risk

Overview

This spreadsheet skill is mostly coherent, but should be reviewed because its recalculation script can persistently modify and execute LibreOffice application macros in the user's profile.

Review before installing or using this skill on a normal desktop profile. The spreadsheet guidance itself is ordinary, but formula recalculation may permanently change your LibreOffice macro environment and could overwrite an existing Module1.xba macro. Prefer running it only in an isolated user account or temporary LibreOffice profile, and keep backups of existing workbooks and LibreOffice macro files before using recalculation.

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

T07 · Tool Hijacking and Spoofing

Error
Location
recalc.py:26
Finding
Untrusted Pre-existing LibreOffice Macro Is Executed Without Integrity Validation## Vulnerability Details **File Location**: `recalc.py`, lines 26-29 and 70-75 **Vulnerability Type**: Untrusted local tool and macro hijacking **Risk Level**: High ### Vulnerable Code ```python if os.path.exists(macro_file): with open(macro_file, 'r') as f: if 'RecalculateAndSave' in f.read(): return True ``` ```python cmd = [ 'soffice', '--headless', '--norestore', 'vnd.sun.star.script:Standard.Module1.RecalculateAndSave?language=Basic&location=application', abs_path ] ``` ### Technical Analysis The script trusts an existing application-level LibreOffice macro solely because its source contains the substring `RecalculateAndSave`. It does not verify the complete macro body, file ownership, permissions, origin, or cryptographic integrity. The subsequent `soffice` invocation executes `Standard.Module1.RecalculateAndSave` from the application macro location. Consequently, an attacker who can modify the user's LibreOffice profile can replace the expected recalculation macro with arbitrary LibreOffice Basic logic while preserving the expected procedure name or text. The substring test then accepts the malicious module, and the script executes it as if it were trusted. This is a tool-hijacking weakness rather than an independent privilege escalation: the malicious macro runs with the operating-system permissions of the user who invokes `recalc.py`. ### Attack Path 1. An attacker, compromised local process, or malicious package obtains write access to the invoking user's LibreOffice profile. 2. The attacker creates or modifies `Module1.xba` under the applicable `Standard` macro directory. 3. The malicious module contains the text or procedure name `RecalculateAndSave`, ensuring that the weak validation at lines 26-29 succeeds. 4. The user or agent follows the documented workflow and runs `python recalc.py workbook.xlsx`. 5. The script invokes the application-level `S ...[truncated 744 chars]
Remediation
## Remediation Suggestions - Do not execute a macro from the user's persistent, application-level LibreOffice profile. - Create a dedicated temporary LibreOffice profile for each run and launch LibreOffice with an isolated `UserInstallation`, such as `-env:UserInstallation=file:///path/to/temporary/profile`. - Install a uniquely named macro only in that isolated profile and remove the entire profile after execution. - If reuse of a macro is unavoidable, validate the complete file against a cryptographic digest of a known-good macro rather than searching for a procedure-name substring. - Verify that macro directories and files are owned by the expected user and are not writable by other users. - Use a unique module and procedure name to reduce collision and hijacking opportunities. - Fail closed if the macro content or execution environment differs from the expected configuration.

T09 · Insecure Skill Coding Practices

Warning
Location
recalc.py:20
Finding
Recalculation Persistently Installs or Overwrites a Global LibreOffice Macro## Vulnerability Details **File Location**: `recalc.py`, lines 20-49 **Vulnerability Type**: Unsafe persistent modification of user-level application configuration **Risk Level**: Medium ### Vulnerable Code ```python def setup_libreoffice_macro(): """Setup LibreOffice macro for recalculation if not already configured""" if platform.system() == 'Darwin': macro_dir = os.path.expanduser('~/Library/Application Support/LibreOffice/4/user/basic/Standard') else: macro_dir = os.path.expanduser('~/.config/libreoffice/4/user/basic/Standard') macro_file = os.path.join(macro_dir, 'Module1.xba') if os.path.exists(macro_file): with open(macro_file, 'r') as f: if 'RecalculateAndSave' in f.read(): return True if not os.path.exists(macro_dir): subprocess.run(['soffice', '--headless', '--terminate_after_init'], capture_output=True, timeout=10) os.makedirs(macro_dir, exist_ok=True) macro_content = '''<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd"> <script:module xmlns:script="http://openoffice.org/2000/script" script:name="Module1" script:language="StarBasic"> Sub RecalculateAndSave() ThisComponent.calculateAll() ThisComponent.store() ThisComponent.close(True) End Sub </script:module>''' try: with open(macro_file, 'w') as f: f.write(macro_content) return True except Exception: return False ``` ### Technical Analysis A workbook recalculation operation writes `Module1.xba` into the user's normal LibreOffice `Standard` macro directory. This is a persistent, application-wide configuration change rather than a temporary resource scoped to the workbook or current process. If `Mod ...[truncated 1703 chars]
Remediation
## Remediation Suggestions - Use a fresh temporary LibreOffice user profile for every recalculation operation. - Pass an isolated `UserInstallation` path to LibreOffice so that no files are written to the user's normal profile. - Delete the temporary profile in a `finally` block after LibreOffice exits. - Never overwrite an existing user macro module as part of workbook processing. - If modifying the normal profile is strictly required, obtain explicit user consent, create a verified backup, use atomic file replacement, and restore the original module after execution. - Choose a collision-resistant module name rather than the generic `Module1.xba`. - Apply restrictive permissions to any generated macro and its containing directory. - Clearly disclose any unavoidable persistent configuration changes in the skill documentation.
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 (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The documented behavior presents the skill as a general spreadsheet helper, but the embedded recalculation workflow can write a LibreOffice macro into the user's configuration directory, a persistent side effect not disclosed in the description. Hidden persistence and description/behavior mismatch are dangerous because users and policy systems may authorize the skill for benign spreadsheet tasks without realizing it alters local application configuration.

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill instructs use of file read/write operations and shell execution (`python recalc.py ...`) but declares no explicit tool scope or permission boundaries. This increases the chance the agent can modify files or invoke shell commands more broadly than users expect, especially in environments where skill metadata is used for enforcement or review.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The manifest description says the skill should be used whenever Claude needs to work with spreadsheets for creating, reading, analyzing, modifying, visualizing, or recalculating files. This scope is very broad and does not define exclusions, narrow trigger phrases, or negative examples, which increases the chance of unintended invocation for ordinary spreadsheet mentions.

Behavior Manipulation

Medium
Category
Prompt Injection
Content
## CRITICAL: Use Formulas, Not Hardcoded Values

**Always use Excel formulas instead of calculating values in Python and hardcoding them.** This ensures the spreadsheet remains dynamic and updateable.

### ❌ WRONG - Hardcoding Calculated Values
```python
Confidence
70% confidence
Finding
Subtle instructions detected that may alter agent decision-making or introduce hidden biases.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The skill includes direct file-modifying operations such as saving modified workbooks, inserting rows, deleting columns, and creating sheets, but does not require a user-facing warning or backup step before altering files. This can lead to accidental data loss, corruption of templates, or overwriting important spreadsheet contents when the skill is invoked on existing documents.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The script silently modifies the user's global LibreOffice profile by installing an application-level macro in the Standard library. Persistently altering a user's office macro environment is risky because it changes trust boundaries outside the target workbook, can interfere with other documents or tooling, and leaves behind executable macro content that may be invoked later.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
return True
    
    if not os.path.exists(macro_dir):
        subprocess.run(['soffice', '--headless', '--terminate_after_init'], 
                      capture_output=True, timeout=10)
        os.makedirs(macro_dir, exist_ok=True)
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The code writes a LibreOffice macro file into the user's profile without an explicit warning or consent at the point of action. Silent persistence of executable macro code is dangerous because users may not realize their office environment has been modified, and that hidden state can affect later document handling and complicate incident response.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if platform.system() == 'Darwin':
            # Check if gtimeout is available on macOS
            try:
                subprocess.run(['gtimeout', '--version'], capture_output=True, timeout=1, check=False)
                timeout_cmd = 'gtimeout'
            except (FileNotFoundError, subprocess.TimeoutExpired):
                pass
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if timeout_cmd:
            cmd = [timeout_cmd, str(timeout)] + cmd
    
    result = subprocess.run(cmd, capture_output=True, text=True)
    
    if result.returncode != 0 and result.returncode != 124:  # 124 is timeout exit code
        error_msg = result.stderr or 'Unknown error during recalculation'
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Low
Confidence
80% confidence
Finding
Launching `soffice` is a subprocess operation, and there is no visible runtime disclosure near execution beyond general docstrings and usage text. Users are told the script uses LibreOffice, but they are not explicitly warned at execution time that it will invoke external commands and potentially alter the workbook as part of recalculation.

Static analysis

No suspicious patterns detected.