T09 · Insecure Skill Coding Practices
- Location
scripts/office/soffice.py:25- Finding
Predictable Shared Library Path Enables LD_PRELOAD Code Execution
- 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) subprocess.run( ["gcc", "-shared", "-fPIC", "-o", str(_SHIM_SO), str(src), "-ldl"], check=True, capture_output=True, ) src.unlink() return _SHIM_SO ``` ### Technical Analysis The LibreOffice compatibility shim uses globally predictable paths in the system temporary directory: - `/tmp/lo_socket_shim.so` - `/tmp/lo_socket_shim.c` The `_ensure_shim()` function treats any pre-existing file at the shared-object path as trusted. It does not verify the file's owner, permissions, type, content, cryptographic digest, or origin. When the runtime determines that an AF_UNIX socket cannot be created, this file is assigned to `LD_PRELOAD` and LibreOffice is launched with it. `LD_PRELOAD` causes the dynamic linker to load the specified shared object into the new process before ordinary dependencies. Constructors and intercepted functions in that object can therefore execute arbitrary native code under the identity of the user running the Skill. The check-then-use sequence is also susceptible to race conditions. Even when the Skill creates the library itself, another local p ...[truncated 1446 chars]- Remediation
View remediation
