Back to skill

Security audit

Xlsx Pro

Security checks for vulnerabilities and agentic risk

Overview

The skill is for spreadsheet work, but its recalculation path changes LibreOffice profile state and loads low-level helper code in ways users are not clearly warned about.

Review before installing. Use it only in an isolated environment or VM, keep backups of spreadsheets, and avoid running the recalculation script against important LibreOffice profiles until it uses a temporary profile, removes the LD_PRELOAD shim or validates it safely, pins dependencies, and makes in-place file/profile changes explicit.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T07 · Tool Hijacking and Spoofing

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

LibreOffice Runtime Hijacking Through LD_PRELOAD-Based Sandbox Bypass

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 ``` ```python _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) try: subprocess.run( ["gcc", "-shared", "-fPIC", "-o", str(_SHIM_SO), str(src), "-ldl"], check=True, capture_output=True, ) except (subprocess.CalledProcessError, FileNotFoundError): pass finally: if src.exists(): src.unlink() return _SHIM_SO ``` ```c int socket(int domain, int type, int protocol) { if (domain == AF_UNIX) { int fd = real_socket(domain, type, protocol); if (fd >= 0) return fd; int sv[2]; if (real_socketpair(domain, type, protocol, sv) == 0) { if (sv[0] >= 0 && sv[0] < 1024) { is_shimmed[sv[0]] = 1; peer_of[sv[0]] = sv[1]; int wp[2]; if (pipe(wp) == 0) { wake_r[sv[0]] = wp[0]; wake_w[sv[0]] = wp[1]; } } return sv[0]; } errno = EPERM; return -1; } return real_socket(domain, type, protocol); } int close(int fd) { if (fd >= 0 && fd < 1024 && is_shimmed[fd]) { int was_liste ...[truncated 2429 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

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

Arbitrary Library Preloading Through a Predictable Shared Temporary Path

Content
View full analysis
Path: """Compile le shim .so s'il n'est pas déjà en cache.""" if _SHIM_SO.exists(): return _SHIM_SO src = Path(tempfile.gettempdir()) / "lo_socket_shim.c" src.write_text(_SHIM_SOURCE) try: subprocess.run( ["gcc", "-shared", "-fPIC", "-o", str(_SHIM_SO), str(src), "-ldl"], check=True, capture_output=True, ) except (subprocess.CalledProcessError, FileNotFoundError): # Si gcc n'est pas disponible ou échoue, on continue sans shim pass finally: if src.exists(): src.unlink() return _SHIM_SO ``` ```python if _needs_shim(): shim = _ensure_shim() env["LD_PRELOAD"] = str(shim) ``` ### Technical Analysis The shared object and its C source use fixed filenames in the system temporary directory. `_ensure_shim()` trusts any existing `lo_socket_shim.so` without checking its owner, permissions, file type, cryptographic digest, or expected contents. On a conventional multi-user system, a shared temporary directory may be writable by other local users. An attacker who can create the predictable path before the Skill runs can place an arbitrary shared object there. The code then returns that file without compiling the expected source and passes it to `LD_PRELOAD`. Fixed-path source creation also creates symlink and time-of-check/time-of-use hazards. ### Attack Path 1. A local attacker predicts the path, such as `/tmp/lo_socket_shim.so`. 2. Before the Skill runs, the attacker creates that file as a malicious shared object containing a constructor or intercepted libc functions. 3. A user invokes spreadsheet recalculation in an env ...[truncated 980 chars]
Remediation
View remediation

T06 · System Persistence

Error
Location
scripts/recalc.py:30
Finding

Persistent and Destructive Modification of the Global LibreOffice Macro Profile

Content
View full analysis
Sub RecalculateAndSave() ThisComponent.calculateAll() ThisComponent.store() ThisComponent.close(True) End Sub """ ``` ```python def setup_libreoffice_macro(): """Configure la macro LibreOffice si pas déjà fait""" macro_dir = os.path.expanduser( MACRO_DIR_MACOS if platform.system() == "Darwin" else MACRO_DIR_LINUX ) macro_file = os.path.join(macro_dir, MACRO_FILENAME) if ( os.path.exists(macro_file) and "RecalculateAndSave" in Path(macro_file).read_text() ): return True if not os.path.exists(macro_dir): try: subprocess.run( ["soffice", "--headless", "--terminate_after_init"], capture_output=True, timeout=10, env=get_soffice_env(), ) except Exception: pass os.makedirs(macro_dir, exist_ok=True) try: Path(macro_file).write_text(RECALCULATE_MACRO) return True except Exception: return False ``` ### Technical Analysis The recalculation workflow installs a macro into the user’s persistent, application-level LibreOffice profile. It uses the generic module filename `Module1.xba`. If that file already exists but does not contain the string `RecalculateAndSave`, the co ...[truncated 1443 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
SKILL.md:23
Finding

Unpinned Third-Party Python Dependency Installation

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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (28)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This second mismatch finding highlights that the skill writes LibreOffice macro/profile state and launches external processes while presenting itself as a general spreadsheet editing skill. Hidden persistence in the user profile and process execution materially increase risk, especially because the primary output may become diagnostic JSON rather than the promised spreadsheet artifact.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

This second mismatch finding highlights that the skill writes LibreOffice macro/profile state and launches external processes while presenting itself as a general spreadsheet editing skill. Hidden persistence in the user profile and process execution materially increase risk, especially because the primary output may become diagnostic JSON rather than the promised spreadsheet artifact.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Injecting a native library via LD_PRELOAD gives the skill process low-level control over libc calls in the spawned application, which is far beyond ordinary spreadsheet manipulation. In the context of an Excel-focused skill, this is especially concerning because it introduces stealthy code-injection behavior unrelated to the declared function and could be repurposed to alter process behavior or execute arbitrary native logic.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Compiling C code at runtime is an unnecessary and dangerous privilege expansion for a spreadsheet-processing helper. In this skill context it is less justifiable because the manifest promises document manipulation, not native code build-and-load behavior, making the mismatch a strong risk indicator and increasing the chance of arbitrary code execution or policy bypass.

Content

No source excerpt is available for this finding.

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 30)May include surrounding context.

python
except ImportError:
    # Fallback si le module office n'est pas disponible
    def get_soffice_env():
        env = os.environ.copy()
        env["SAL_USE_VCLPLUGIN"] = "svp"
        return env

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

python
except ImportError:
    # Fallback si le module office n'est pas disponible
    def get_soffice_env():
        env = os.environ.copy()
        env["SAL_USE_VCLPLUGIN"] = "svp"
        return env

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Lines L55-L57 tell the user to remove a LibreOffice macro file to fix configuration issues, which is a destructive action affecting local application state. The documentation does not warn that this deletes existing macro configuration and may remove custom macros or settings.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill advertises code and shell-capable workflows but does not declare any explicit tool scope or permission boundaries. In practice this increases the blast radius of the skill because file access, shell execution, and environment access are available without a documented least-privilege contract.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file uses French-only operational instructions, including the core description that governs when and how the skill should be used. Under the policy, forcing a specific language without user opt-in or justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · README.md (reported line 27)May include surrounding context.

LibreOffice (pour recalcul des formules)

bash
# Ubuntu/Debian
sudo apt-get install libreoffice-calc libreoffice-common

Règles de Qualité

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · README.md (reported line 28)May include surrounding context.

LibreOffice (pour recalcul des formules)

bash
# Ubuntu/Debian
sudo apt-get install libreoffice-calc libreoffice-common

Règles de Qualité

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

LibreOffice (pour recalcul des formules)

bash
# Ubuntu/Debian
sudo apt-get install libreoffice-calc libreoffice-common

Règles de Qualité

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest positions the skill as an Excel/tableur manipulation capability whose deliverable should be a spreadsheet file. This module instead wraps soffice generically, including an example converting a DOCX to PDF, which reflects broad Office document execution/conversion behavior rather than specifically handling .xlsx/.xlsm/.csv/.tsv spreadsheet tasks.

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 48)May include surrounding context.

python
_exit(0) quand le socket listener de soffice.bin se ferme (après conversion).
    """
    env = get_soffice_env()
    return subprocess.run(["soffice"] + args, env=env, **kwargs)


# ---------------------------------------------------------------------------

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module silently writes source code to a temp directory and compiles a shared library without explicit disclosure or consent. Even if intended as an engineering workaround, doing this opaquely reduces auditability and can surprise operators, and temporary-file handling around build artifacts increases the chance of tampering or unsafe persistence.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
97% confidence
Finding

The code writes C source to a temporary directory and invokes gcc to build a shared object at runtime, then later loads it with LD_PRELOAD. Runtime native-code compilation materially expands capability and attack surface, and if the temp path or resulting artifact is tampered with by another local process, it can become arbitrary code execution in the LibreOffice process.

Content

Scanner excerpt · scripts/office/soffice.py (reported line 76)May include surrounding context.

python
src = Path(tempfile.gettempdir()) / "lo_socket_shim.c"
    src.write_text(_SHIM_SOURCE)
    try:
        subprocess.run(
            ["gcc", "-shared", "-fPIC", "-o", str(_SHIM_SO), str(src), "-ldl"],
            check=True,
            capture_output=True,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The embedded LibreOffice macro recalculates and then stores the workbook, modifying the input file in place without making that side effect explicit to the user. In a file-manipulation skill this is relevant because the user may expect analysis or validation, not destructive overwrite of the original workbook.

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

python
def has_gtimeout():
    """Vérifie si gtimeout est disponible sur macOS"""
    try:
        subprocess.run(
            ["gtimeout", "--version"], capture_output=True, timeout=1, check=False
        )
        return True

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script writes a global LibreOffice application macro into the user's profile, creating persistent cross-document state outside the target spreadsheet. That exceeds the stated purpose of recalculating one workbook and can alter behavior for future LibreOffice sessions or conflict with existing user macros.

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

python
# Créer répertoire macro si nécessaire
    if not os.path.exists(macro_dir):
        try:
            subprocess.run(
                ["soffice", "--headless", "--terminate_after_init"],
                capture_output=True,
                timeout=10,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script silently creates or overwrites a macro file in the LibreOffice profile without notice or consent, causing hidden persistent modification to user configuration. Silent profile modification is risky because it is unexpected, hard to audit, and can interfere with existing macros or trust assumptions.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
80% confidence
Finding

The script launches LibreOffice on a user-supplied spreadsheet path, which can trigger processing of complex or malicious workbook content in a large external application. While there is no shell injection here, invoking soffice on untrusted files expands the attack surface and can expose the host to parser vulnerabilities or unintended macro/document behaviors depending on LibreOffice configuration.

Content

Scanner excerpt · scripts/recalc.py (reported line 127)May include surrounding context.

python
cmd = ["gtimeout", str(timeout)] + cmd

    try:
        result = subprocess.run(cmd, capture_output=True, text=True, env=get_soffice_env(), timeout=timeout+10)
    except subprocess.TimeoutExpired:
        return {"error": "Timeout lors du recalcul"}

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The user-facing operational instructions and descriptions are presented in French only, which forces a specific language on users. The file does not indicate that the skill is region-specific or offer an alternative language or opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

In a markdown file, system-affecting operations should be disclosed when they may impact system integrity. The prerequisite section includes sudo apt-get install commands, but there is no warning that this performs package installation on the machine and may require administrative privileges.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The markdown explicitly instructs creating, loading, modifying, and saving spreadsheet files, which can affect user data. Although file editing is core to the skill, there is no clear user-facing warning to work on copies or confirm overwrite behavior when modifying existing spreadsheets.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.