Back to skill

Security audit

anthropic-pptx

Security checks for vulnerabilities and agentic risk

Overview

This presentation skill has useful PPTX functionality, but it needs review because it uses unsafe local execution patterns, mutable global installs, broad triggers, and under-disclosed Office document handling.

Install only if you are comfortable reviewing and constraining its local execution. Use it in an isolated workspace or container for untrusted presentations, avoid global package installation where possible, and be aware that it contains Word/DOCX helpers beyond the PPTX description.

Vulnerability Patterns
  • 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
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/office/soffice.py:28
Finding
Predictable LD_PRELOAD Artifact Enables Local Code Execution<![CDATA[ ## Vulnerability Details **File Location**: `scripts/office/soffice.py`, lines 28-64 **Vulnerability Type**: Unsafe temporary file handling and unverified dynamic-library injection **Risk Level**: High ### Vulnerable Code ```python def get_soffice_env() -> dict: env = os.environ.copy() env["SAL_USE_VCLPLUGIN"] = "svp" if _needs_shim(): shim = _ensure_shim() env["LD_PRELOAD"] = str(shim) return env def run_soffice(args: list[str], **kwargs) -> subprocess.CompletedProcess: env = get_soffice_env() return subprocess.run(["soffice"] + args, env=env, **kwargs) _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 native shim and its C source are placed at fixed, predictable names in the shared system temporary directory. If `lo_socket_shim.so` already exists, `_ensure_shim()` accepts it without verifying its ownership, permissions, file type, contents, or cryptographic integrity. When `_needs_shim()` detects that an AF_UNIX socket cannot be created, the unverified file is assigned to `LD_PRELOAD`. LibreOffice is then launched with that environment. The operating-system loader executes the constructors and intercepted functions in the supplied shared object before the normal application code. The source and output filenames are also susceptible to symlink and time-of-check/time-of-use attacks because they are written and compiled through sha ...[truncated 1506 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not reuse a fixed library from a shared temporary directory. 2. Create a private temporary directory using `tempfile.TemporaryDirectory()` and ensure it is accessible only to the current user, normally with mode `0700`. 3. Create source and output files with exclusive-creation semantics and reject symbolic links or non-regular files. 4. Compile the library into the private directory for each invocation, or package a reviewed binary whose cryptographic digest is verified before use. 5. Before setting `LD_PRELOAD`, verify the file's owner, permissions, type, canonical location, and expected digest. 6. Avoid inheriting unrelated preload variables from the parent environment. Construct a minimal subprocess environment and explicitly remove unexpected `LD_PRELOAD` or similar loader-control variables. 7. Prefer a LibreOffice configuration that does not require native function interception. If the shim remains necessary, isolate LibreOffice in a dedicated low-privilege sandbox with narrowly scoped filesystem access. 8. Add tests that pre-create files and symlinks at the old predictable paths and confirm that they are never loaded or overwritten. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/office/unpack.py:53
Finding
Unbounded Extraction of Untrusted Office Archives<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/office/unpack.py`, lines 53-54 - `scripts/office/validate.py`, lines 71-74 - `scripts/office/validators/base.py`, lines 798-802 - `scripts/office/validators/docx.py`, lines 187-189 - `scripts/office/validators/redlining.py`, lines 59-64 **Vulnerability Type**: Unrestricted archive extraction and decompression-bomb exposure **Risk Level**: Medium ### Vulnerable Code The primary unpacking path extracts every member without applying resource limits: ```python with zipfile.ZipFile(input_path, "r") as zf: zf.extractall(output_path) ``` The validation path uses the same unrestricted operation: ```python if path.is_file() and path.suffix.lower() in [".docx", ".pptx", ".xlsx"]: temp_dir = tempfile.mkdtemp() with zipfile.ZipFile(path, "r") as zf: zf.extractall(temp_dir) unpacked_dir = Path(temp_dir) ``` The original-file validation path likewise extracts an entire archive: ```python with tempfile.TemporaryDirectory() as temp_dir: temp_path = Path(temp_dir) with zipfile.ZipFile(self.original_file, "r") as zip_ref: zip_ref.extractall(temp_path) ``` ### Technical Analysis PPTX, DOCX, and XLSX files are ZIP containers and may be supplied by an untrusted user. The extraction paths do not inspect archive metadata before extraction and impose no limits on: - Archive member count - Expanded size of an individual member - Aggregate expanded size - Compression ratio - Filesystem inode consumption - Time spent decompressing and subsequently parsing extracted XML A small archive can therefore declare or produce a very large amount of expanded data. After extraction, the unpacking workflow recursively discovers and parses XML and relationship files, which can further amplify CPU and memory consumption. The audit did not establish a path-traversal exploit against the runtime's `zipfile.extractall()` implementation. The confirmed problem is unbounded resource consumpti ...[truncated 1262 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Inspect every `ZipInfo` entry before extraction. 2. Enforce conservative limits for: - Maximum archive member count - Maximum expanded size per member - Maximum aggregate expanded size - Maximum permitted compression ratio - Maximum path length 3. Reject encrypted entries, unsupported compression methods, symbolic-link-like entries, and other non-regular member types unless explicitly required. 4. Canonicalize every destination and verify that it remains beneath the intended extraction root. 5. Extract members individually through bounded streams instead of calling `extractall()`. Track actual bytes written rather than relying only on archive metadata. 6. Abort immediately when any resource threshold is exceeded and remove all partial extraction output. 7. Apply process-level CPU, memory, file-size, inode, and execution-time limits when parsing untrusted Office files. 8. Use private temporary directories and guarantee cleanup through context managers in every validation path. 9. Apply the same centralized safe-extraction helper consistently across `unpack.py`, `validate.py`, and all validators. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:228
Finding
Unpinned Third-Party Package Installation Instructions<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 228-230 **Vulnerability Type**: Mutable and unverified software supply-chain dependencies **Risk Level**: Medium ### Vulnerable Code ```bash pip install "markitdown[pptx]" pip install Pillow npm install -g pptxgenjs ``` ### Technical Analysis The Skill instructs the Agent to install packages from mutable public registries without version constraints, hashes, lockfiles, provenance checks, or an isolated environment. The effective code installed by these commands can change after the Skill itself has been reviewed. The npm command additionally performs a global installation, expanding the affected environment and potentially changing commands or modules used by other tasks. Package installation can execute build backends, setup hooks, native compilation, or npm lifecycle scripts depending on the selected package and dependency graph. No evidence was found that these specific package names are intentionally malicious. The confirmed issue is that the instructions do not constrain or authenticate the versions and transitive dependencies that will be installed. ### Attack Path 1. An Agent follows the dependency setup instructions when one or more packages are unavailable locally. 2. The package manager resolves the newest versions and transitive dependencies available from its configured registry at that time. 3. A package publisher account, registry entry, release process, or transitive dependency has been compromised, or a future release introduces malicious installation behavior. 4. The package manager downloads and installs that mutable code without verifying a project-provided lockfile or expected hashes. 5. Installation hooks or subsequently imported package code execute with the permissions of the Agent process. 6. For the global npm installation, the resulting package can also influence later tasks using that shared runtime. ### Impact Assessment A compromised dependency can exec ...[truncated 470 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin every direct dependency to a reviewed exact version. 2. Maintain lockfiles that include all transitive dependencies. 3. For Python packages, use a hash-verified requirements file and installation with `--require-hashes`. 4. For npm packages, use a project-local dependency, commit the lockfile, and use deterministic installation such as `npm ci` rather than `npm install -g`. 5. Disable npm lifecycle scripts where they are not required, and explicitly review packages that require native builds or installation hooks. 6. Install dependencies in an isolated virtual environment or disposable container rather than the Agent's shared global runtime. 7. Configure approved registries explicitly and use package provenance or signature verification where supported. 8. Periodically scan pinned dependencies for known vulnerabilities, but update them only through a reviewed and tested process. 9. Document the expected package digests and minimum required functionality so replacement or compromised packages can be detected. ]]>
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
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (56)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This is a clear description-behavior mismatch. The declared purpose says the skill should be used whenever a .pptx file or presentation/slides/deck is involved. However, the supplied code is a helper for DOCX processing: it opens input_dir/word/document.xml, parses WordprocessingML, removes proofing/revision-related XML, and merges adjacent <w:r> runs with identical formatting. Nothing in the code handles .pptx files, slide structures, presentation layouts, speaker notes, or other PowerPoint-specific content. The primary purpose, file type, and resource paths are materially different from the declaration.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description is narrowly and repeatedly about .pptx/presentation workflows. The supplied code does not handle PowerPoint files, slides, layouts, speaker notes, comments, or any presentation functionality. Instead, it modifies WordprocessingML inside a DOCX-style directory structure, merging adjacent <w:ins> and <w:del> tracked-change elements and analyzing tracked-change authors from document.xml or a .docx zip. This is a materially different primary purpose and resource domain, so the description does not accurately represent the code.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The declared description says this skill should be used any time a .pptx file is involved and lists a wide range of presentation-related operations such as creating decks, reading/parsing PPTX content, editing presentations, splitting/combining files, and working with notes/comments/layouts. The supplied code is much narrower and different in focus: it repackages an already-unpacked Office document directory into an Office ZIP container, with optional schema validation/repair, and it supports DOCX and XLSX as well as PPTX. While packaging an unpacked directory into a .pptx could be one supporting use case under 'creating or touching' a PPTX, the code does not match the broad declared purpose and has materially different primary behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description promises a broad .pptx-focused skill for opening, creating, editing, parsing, and otherwise handling presentation files. The supplied code does not implement those presentation operations directly. Instead, it is infrastructure for running LibreOffice in sandboxed environments by altering environment variables and, when needed, generating and compiling a shared library that intercepts socket-related libc calls. While this helper could support document conversion workflows that might include .pptx, its primary purpose is system-level execution compatibility for soffice across document types, not presentation-specific file handling. That is a materially different purpose and includes undeclared capabilities such as runtime native code compilation and LD_PRELOAD-based behavior modification.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The description claims a broad .pptx skill that should trigger for essentially any presentation-related operation. The code, however, is a narrow archive-unpacking utility for Office files generally, not a comprehensive PPTX manipulation skill. Its primary purpose is extracting OOXML package contents and normalizing XML formatting, with extra DOCX-only cleanup operations. That is materially different from the declared behavior, and it also supports file types (.docx, .xlsx) and capabilities not mentioned in the declaration. Therefore this is a clear description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The description claims this skill should be used whenever a .pptx file is involved in any way, implying a broad presentation-processing skill for creating, reading, editing, splitting, combining, and extracting content from PowerPoint files. The actual code is much narrower and materially different: it is a validation utility for Office document XML, including .pptx but also .docx and .xlsx. Its core function is schema validation, plus optional Word redlining checks and limited auto-repair of XML issues. That is not an implementation detail of a general PPTX manipulation skill; it is a distinct primary purpose. The code also includes capabilities outside the declared scope (.docx/.xlsx validation and Word redlining). Therefore the declared description does not accurately represent the actual behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description says the skill should be used whenever a .pptx file is involved and implies a PowerPoint-focused capability set. The supplied code does not implement PPTX file operations; it only re-exports validator classes from several modules. It also includes DOCX and redlining validators, expanding beyond the declared PPTX-only scope, and the docstring explicitly references Word document processing. That makes the actual code behavior materially different from the declared purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The description claims this skill should be triggered for any .pptx-related task, including creating decks, reading presentation content, extracting text, editing slides, and other presentation operations. The supplied code does none of that. Instead, it provides a base validator for unpacked Office Open XML packages: it enumerates XML and .rels files, checks syntax, namespace declarations, unique IDs, relationship targets and relationship IDs, content type declarations, and validates files against XSD schemas. It also includes a narrow repair function that adds xml:space='preserve' where needed. Additionally, the code is broader than the declared scope because it explicitly maps schemas for word, ppt, and xl content. This is a materially different primary purpose, so the description does not accurately represent the code.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This is a clear description-behavior mismatch. The declared purpose says the skill should be used whenever a .pptx file or presentations/slides are involved. The supplied code is specifically for validating Word document XML against XSD-related constraints, with WordprocessingML namespaces and checks for Word constructs like paragraphs, comment markers, deletions/insertions, and durable IDs. It even extracts /word/document.xml from a ZIP, which is characteristic of .docx, not .pptx. The primary purpose, file type, and trigger domain are materially different from the declaration.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The description claims a general-purpose PowerPoint skill for essentially any operation involving .pptx files, including creation, editing, parsing text, combining/splitting, templates, notes, and comments. The supplied code does not implement those capabilities. Instead, it is a specialized validator for PowerPoint XML components, focused on consistency and schema checks within unpacked PPTX contents. This is a materially narrower and different primary purpose than the declared description, so the description does not accurately represent the actual behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This is a clear description-behavior mismatch. The declared purpose says the skill should be used for any .pptx/presentation-related task. The supplied code does not operate on PowerPoint files at all. Instead, it works specifically with Word DOCX files, inspecting word/document.xml for <w:ins> and <w:del> tracked-change elements, removing tracked changes for a given author, comparing text content against an original DOCX, and optionally generating a git word diff. Its primary purpose is validating Word redlining behavior, not handling presentations. That is a materially different function and file type from the declared description.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The description is far broader than the code’s real functionality. This script does not provide general .pptx handling; it only generates thumbnail grid images from an input PowerPoint. It reads limited structural XML metadata (slide relationships and hidden flags) and converts slides to JPEG thumbnails, but it does not extract slide text, create or edit presentations, manipulate templates/notes/comments, or combine/split files. The primary purpose is visual thumbnail generation for quick slide review, which is materially narrower and different from the declared 'use for any .pptx file involved in any way' purpose.

Vague Triggers

High
Confidence
98% confidence
Finding
The activation rule is extremely broad: it triggers on generic words like 'deck,' 'slides,' or 'presentation' and says to use the skill whenever a .pptx file is involved in any way. In an agent setting, overbroad triggers can route ordinary user requests into a powerful shell/file-processing workflow, expanding attack surface and increasing the chance of unsafe handling of untrusted content or unnecessary command execution.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
This file implements Word .docx tracked-change manipulation and author-analysis logic inside a skill explicitly scoped to .pptx presentations. That capability mismatch is dangerous because out-of-scope document-processing code can be invoked on unrelated Office content, increasing the attack surface for unauthorized document inspection or modification and bypassing user expectations about what the skill should touch.

Hidden Instructions

High
Category
Prompt Injection
Content
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://schemas.openxmlformats.org/package/2006/relationships"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://schemas.openxmlformats.org/package/2006/relationships"
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://schemas.openxmlformats.org/package/2006/relationships"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://schemas.openxmlformats.org/package/2006/relationships"
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://schemas.openxmlformats.org/package/2006/relationships"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://schemas.openxmlformats.org/package/2006/relationships"
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
def get_soffice_env() -> dict:
    env = os.environ.copy()
    env["SAL_USE_VCLPLUGIN"] = "svp"

    if _needs_shim():
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.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The file implements DOCX-specific validation and repair logic even though the skill is declared as PPTX-only. This scope mismatch is dangerous because it expands the skill's effective file-handling surface beyond its advertised purpose, enabling unreviewed processing of Word documents and associated XML/ZIP content that users and reviewers would not expect in a PowerPoint-only skill.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
This file implements Word DOCX redlining validation inside a skill declared as PPTX-specific, which is a capability/intent mismatch. Such drift is dangerous because it expands the effective attack surface and can cause the agent to access or transform file types outside the user's expected scope, weakening trust boundaries and increasing the chance of unsafe tool invocation.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill instructs use of shell commands, file reads/writes, and likely environment access, but it declares no explicit tool scope or permissions boundary. This creates unnecessary ambiguity about what the skill is allowed to do and increases the chance an agent will execute powerful local operations on untrusted presentation files without adequate restriction.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The example XML hard-codes `lang="en-US"`, and the surrounding guidance presents it as the correct pattern to copy when editing slide content. That effectively imposes a specific locale on generated content without offering a user choice or documenting a justified regional constraint.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The script writes new slide and relationship files and later updates existing PPTX XML files, which changes user data on disk. While there are status prints after completion, there is no prior warning or confirmation before these modifications occur, and the module docstring describes functionality but does not clearly warn that existing package contents will be edited.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The functions that parse .docx archives and infer tracked-change authors extract document metadata unrelated to stated pptx operations. In a presentation-only skill, this creates unjustified access to sensitive authorship information and supports hidden analysis of non-presentation files, which is especially concerning because author identities and review history may be confidential.

Session Persistence

Medium
Category
Rogue Agent
Content
</xsd:sequence>
     <xsd:attribute name="pos" type="a:ST_PositiveFixedPercentage" use="required"/>
   </xsd:complexType>
   <xsd:complexType name="CT_GradientStopList">
     <xsd:sequence>
       <xsd:element name="gs" type="CT_GradientStop" minOccurs="2" maxOccurs="10"/>
     </xsd:sequence>
Confidence
75% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Static analysis

No suspicious patterns detected.