Back to skill

Security audit

lhx

Security checks for vulnerabilities and agentic risk

Overview

This spreadsheet skill is useful and mostly purpose-aligned, but its formula recalculation script makes persistent changes to the user's LibreOffice macro profile that are not fully scoped or contained.

Install only if you are comfortable with an agent running LibreOffice locally and allowing this skill to alter your LibreOffice macro profile. Prefer running it in an isolated user profile or container, avoid elevated privileges, and keep backups of important spreadsheets and LibreOffice macros before using formula recalculation.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
recalc.py:18
Finding

Persistent Global LibreOffice Macro Overwrite

Content
View full analysis
Sub RecalculateAndSave() ThisComponent.calculateAll() ThisComponent.store() ThisComponent.close(True) End Sub ''' try: with open(macro_file, 'w') as f: f.write(macro_content) return True except Exception: return False ``` ### Technical Analysis The recalculation script installs a macro into LibreOffice's persistent, global user profile rather than using an isolated profile created specifically for the current operation. The target filename, `Module1.xba`, is generic and predictable. If that module already exists but does not contain the string `RecalculateAndSave`, opening it with mode `w` tru ...[truncated 2273 chars]
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 (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill is described as a general spreadsheet creation/editing/analysis capability, but its documented workflow requires running an external recalculation script that configures LibreOffice and writes a macro into the user's environment. This mismatch prevents informed consent and can hide side effects that materially change the host system beyond simple spreadsheet processing.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill instructs use of file read/write operations and shell execution (python recalc.py) but declares no explicit tool scope or permissions boundaries. In an agent setting, this can cause the skill to be invoked with broader capabilities than the user expects, increasing the risk of unintended file modification or command execution.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The activation description is very broad and could match many ordinary spreadsheet-related requests, causing the skill to trigger in situations where shell execution, file writes, or workbook modification are unnecessary. Over-broad routing increases the chance that risky operations occur implicitly rather than only when specifically requested.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The workflow makes formula recalculation mandatory via python recalc.py, yet the skill description does not clearly warn that this runs an external script and automatically configures LibreOffice. Hidden command execution and environment modification are significant side effects that can surprise users and expand the attack surface.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The examples demonstrate saving modified workbooks and performing structural changes like row/column insertion and deletion without any user-facing warning. In practice, this can normalize destructive file operations and lead an agent to overwrite or alter user spreadsheets without clear disclosure or confirmation.

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

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script writes a macro into the user's global LibreOffice application profile, permanently changing office automation behavior outside the scope of this single run. In a skill that processes untrusted spreadsheets, modifying a global macro store increases attack surface, creates cross-session persistence, and may interact dangerously with other documents or user workflows.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The recalculation design depends on spawning external office software to open and process attacker-controlled spreadsheet files. In the context of a spreadsheet skill, this is more dangerous because spreadsheet parsers, embedded content, external links, and file-format handling in LibreOffice expand the attack surface beyond simple file parsing in Python, potentially leading to code execution, data exfiltration, or denial of service if LibreOffice is exploited or coerced into network/resource access.

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)

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'

Static analysis

No suspicious patterns detected.