T07 · Tool Hijacking and Spoofing
- Location
recalc.py:22- Finding
Execution of an Unverified Persistent LibreOffice Macro
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a legitimate spreadsheet helper, but its formula recalculation helper persistently modifies the user's global LibreOffice macro profile without adequate isolation or consent.
Review before installing. Use this only if you are comfortable with a spreadsheet skill that can run LibreOffice and change your LibreOffice macro profile. Prefer an updated version that uses a temporary isolated LibreOffice profile, verifies any macro it invokes, avoids overwriting existing macros, and asks before modifying existing workbooks or application configuration.
recalc.py:22Execution of an Unverified Persistent LibreOffice Macro
recalc.py:19Persistent Overwrite of the Global LibreOffice Macro Module
The declared purpose is general spreadsheet manipulation, but the documented behavior includes external subprocess execution and modification of LibreOffice macro/configuration on disk. This mismatch is dangerous because users or orchestrators may invoke the skill expecting routine spreadsheet handling while it performs higher-risk side effects that expand persistence and execution surface beyond the stated purpose.
The skill instructs the agent to write files and invoke shell commands such as running recalc.py and configuring LibreOffice, but it does not declare any explicit tool scope or permissions boundaries. That creates an authorization and review gap: a broadly-triggered spreadsheet skill can gain effective file-write and subprocess capability without clear constraints on what paths, files, or commands are permitted.
The activation criteria are extremely broad, covering nearly any spreadsheet-related task across multiple file types and operations. In context, that increases the chance the skill is auto-selected for benign requests and then exercises file-writing or shell-based recalculation behavior unnecessarily, raising the exposure of those capabilities.
Subtle instructions detected that may alter agent decision-making or introduce hidden biases.
Always use Excel formulas instead of calculating values in Python and hardcoding them. This ensures the spreadsheet remains dynamic and updateable.
The skill describes editing existing workbooks with operations like insert_rows, delete_cols, overwriting cells, and saving modified files, but it does not require backups, confirmation, or warnings about irreversible changes. In spreadsheet contexts, these actions can silently break formulas, corrupt templates, or destroy user data, especially when combined with automatic save behavior.
The script silently writes a global LibreOffice application macro into the user's profile, changing persistent local execution behavior outside the scope of the current task. In a spreadsheet-handling skill that processes potentially untrusted files, modifying application-level macro state without explicit consent increases attack surface, surprises users, and can weaken trust boundaries if other documents later invoke or rely on that macro environment.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
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"?>
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
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 calls execute external commands. Without careful input validation, this enables command injection.
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"
No suspicious patterns detected.