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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

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.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Behavior Manipulation

Medium
Category
Prompt Injection
Confidence
70% confidence
Finding

Subtle instructions detected that may alter agent decision-making or introduce hidden biases.

Content

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

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

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
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.

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 · recalc.py (reported line 32)May include surrounding context.

python
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)

Missing User Warnings

Medium
Category
Not specified by scanner
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.

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 · recalc.py (reported line 85)May include surrounding context.

python
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

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 · recalc.py (reported line 93)May include surrounding context.

python
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'

Missing User Warnings

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.