xlsx
- Type
- Skill
- Scanned
- Oct 29, 2026
- Version
- ca45fc496a34
- Files read
- 53
This skill provides instructions and helper scripts for AI agents to create, edit, validate, and recalculate Excel spreadsheets using Python libraries and LibreOffice. The main risks are a predictable /tmp path used to compile and load an LD_PRELOAD shared library for LibreOffice in restricted environments, and XML External Entity (XXE) resolution in the bundled Office XML validator.
What it can reach
- Files
- Reads, creates, and modifies spreadsheet and Office files on disk, and creates temporary profiles and shared libraries in the system temp directory.
- Shell commands
- Executes LibreOffice (soffice), gcc, timeout/gtimeout, and git via subprocesses, and instructs the agent to run Python scripts, markitdown, and pip.
Findings
-
MediumPredictable temporary file path used for LD_PRELOAD shared library
skills/xlsx/scripts/office/soffice.py:50
When Unix domain sockets are blocked in the runtime environment, soffice.py writes C source code to /tmp/lo_socket_shim.c, compiles it to /tmp/lo_socket_shim.so, and preloads it into LibreOffice via LD_PRELOAD. Because it uses fixed filenames in the world-writable temporary directory and reuses /tmp/lo_socket_shim.so if it already exists, another local user or process on a shared system can plant or replace the file to execute arbitrary code when LibreOffice runs.
Fix: Write the C source and compile the shared object inside a private directory created with tempfile.mkdtemp() (mode 0700) instead of directly in tempfile.gettempdir().
-
MediumXML External Entity (XXE) resolution enabled in lxml parser
skills/xlsx/scripts/office/validators/base.py:167
While other parts of the codebase use defusedxml, BaseSchemaValidator and its subclasses parse unpacked Office XML files using lxml.etree.parse() with default settings. By default, lxml resolves external entities (resolve_entities=True), allowing a crafted Office document passed to validate.py to include local files via SYSTEM entities and leak their contents through validation error messages.
Fix: Use lxml.etree.XMLParser(resolve_entities=False, no_network=True, load_dtd=False) for all lxml.etree.parse() calls.