Back to skill

Security audit

Pdf Toolkit

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed local document-processing toolkit with expected file writes and a clearly documented remote text-to-speech feature, though users should be careful with sensitive files and runtime dependency installation.

Install only if you are comfortable with a local script that can read and write the file paths you ask it to use. Avoid the TTS command for confidential text because it sends input to an external service, and prefer a locked or reviewed dependency environment if you need stronger supply-chain control.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T08 · Insecure Dependencies

Warning
Location
src/main.py:4
Finding

Unpinned Runtime Dependencies Create a Supply-Chain Execution Risk

Content
View full analysis

Vulnerability Details

File Location: src/main.py:4-12
Vulnerability Type: Unpinned automatically installed third-party dependencies
Risk Level: Medium

Vulnerable Code

python
# /// script
# requires-python = ">=3.12"
# dependencies = [
#   "pypdf",
#   "pdfplumber",
#   "reportlab",
#   "python-docx",
#   "edge-tts",
#   "pillow",
# ]
# ///

The project wrapper automatically invokes this dependency-enabled script:

bash
exec uv run "$SKILL_DIR/src/main.py" "$@"

The documented behavior confirms that dependency resolution and installation occur at runtime:

markdown
- `uv run` reads the inline `# /// script` dependency block in `main.py` and auto-installs Python packages in an isolated environment — no pip install or venv setup needed.

Technical Analysis

All six Python dependencies are declared without exact versions. No reviewed lockfile or integrity hashes are present in the audited project. Consequently, uv run may resolve and install package releases that were not part of this audit.

Isolation of the package environment does not prevent malicious package code from inheriting the skill process's effective filesystem and network permissions. Imported dependencies execute in the same Python process as the toolkit. A compromised upstream release, package-maintainer account, transitive dependency, or package-index response could therefore introduce code execution after the skill itself has been reviewed.

The relevant execution chain spans:

  • src/main.py:4-12, where unconstrained dependencies are declared.
  • pdf-toolkit.sh:6, where uv run initiates dependency resolution.
  • SKILL.md:172, where automatic installation is explicitly documented.

Attack Path

  1. An attacker compromises an upstream dependency, one of its transitive dependencies, its publisher account, or the package distribution channel.
  2. A malicious version remains compatible with the unconstrained dependency declarations.
  3. A user in ...[truncated 1144 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin every direct dependency to an exact, reviewed version rather than using unconstrained package names.
  2. Generate and commit a uv.lock file containing the complete resolved dependency graph.
  3. Execute with locked or frozen dependency resolution so runtime execution fails instead of silently selecting newer releases.
  4. Use package hashes or another artifact-integrity verification mechanism where supported.
  5. Perform dependency updates through a controlled review process that includes vulnerability scanning, changelog review, and regression testing.
  6. Configure trusted package indexes explicitly and avoid fallback to untrusted or unexpected package sources.
  7. Consider prebuilding and distributing a reviewed environment or immutable artifact so normal skill invocation does not install code from the network.
  8. Run the skill with least privilege and restrict filesystem and network access to reduce the impact of a compromised dependency.
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (16)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The description presents a broad PDF/DOCX/OCR/text-to-speech toolkit, but this code chunk specifically performs document format conversion using pandoc or libreoffice. That is a materially different and more generic capability than the listed triggers, which emphasize PDF operations, OCR, DOCX handling, and TTS. While document conversion could indirectly relate to DOCX/PDF workflows, the actual behavior here is not accurately represented by the declared description and triggers for this chunk. There is no evidence of undeclared dangerous behavior or inconsistent resource access; the mismatch is primarily that the implemented capability is different from the declared one.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The code chunk does relate to PDF processing, so part of the declared purpose is aligned: it can extract text from PDFs. However, the implemented behavior is narrower and also different in important ways. It contains undeclared capabilities for extracting tables and embedded images from PDFs, including saving image files to an output directory. Those capabilities are not mentioned in the description or triggers. Conversely, many declared capabilities such as DOCX handling, OCR, text-to-speech, MP3 conversion, and PDF merge/split/rotate/info are not present in this code chunk. While absence alone in a partial chunk would not always be a mismatch, the presence of materially undeclared extraction behaviors means the description does not accurately represent this code chunk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill explicitly instructs the agent to execute a local script via shell and states it can read from and write to any host path supplied by the caller, yet it declares no tool scope or permission boundaries. In an agent environment, this missing restriction materially increases the risk of arbitrary file access and shell execution beyond the intended workspace, especially because uv run may fetch/install dependencies at runtime.

Content

No source excerpt is available for this finding.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · src/doctor.py (reported line 71)May include surrounding context.

python
}
        mod_name = module_map.get(pkg.replace("-", "_"), pkg.replace("-", "_"))
        try:
            __import__(mod_name)
            available = True
        except ImportError:
            available = False

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file is named extract_text.py and begins with a text-extraction function, but it additionally implements table extraction and image extraction with filesystem writes. That broadens behavior beyond what the file's apparent documented role suggests, creating an intent mismatch between the code's presentation and its actual operations.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest emphasizes reading PDFs, extracting text, OCR, DOCX handling, and text-to-speech, while this file also implements extraction of embedded images and writes them to disk. In a module named extract_text.py, persisting binary image files is a materially different capability than text extraction and is not obviously required by the stated purpose here.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest describes a toolkit for PDF files, DOCX documents, OCR, text-to-speech, and related PDF operations, but the CLI help also exposes a generic convert command for converting document formats. That broad conversion capability is not reflected in the manifest description or trigger list, so the code presents functionality beyond what the skill claims to do.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The TTS command accepts either raw user text or a file path and forwards that content to tts_to_mp3(...), but this service layer provides no user-facing disclosure that the content may be sent to an external provider. In a document-processing skill, users may reasonably expect local-only handling, so this creates a real confidentiality and privacy risk if sensitive text or file contents are transmitted off-host.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The TTS path uses edge_tts.Communicate(...).save(...), which relies on a remote service rather than a purely local synthesizer. That means text supplied directly or extracted from local PDF/DOCX files can be transmitted off-host, conflicting with the skill's stated local-only document-processing purpose and creating a privacy/data-handling risk.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This implementation can send extracted contents of user-provided PDFs, DOCX files, or raw text to an external network-backed TTS provider. In the context of a local document toolkit, that creates an unnecessary exfiltration channel for potentially sensitive document contents and is more dangerous because users may reasonably expect all processing to remain local.

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 · src/utils.py (reported line 137)May include surrounding context.

python
Raises RuntimeError on timeout.
    """
    try:
        result = subprocess.run(
            cmd,
            input=input_data,
            capture_output=True,

Scope Creep

Low
Category
Excessive Agency
Confidence
89% confidence
Finding

The skill states it can read from and write to any host path the caller supplies and is not limited to the workspace, which broadens access far beyond least privilege. In combination with shell-based execution and optional networked TTS, this makes misuse more dangerous because an agent could be induced to access sensitive host files or overwrite important data outside the expected sandbox.

Content

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

md
- `libreoffice` is an optional alternative to `pandoc` for `convert` because it can handle document conversions that `pandoc` may not support well.

## File Access And Network Behavior
- This skill operates on the file paths provided by the caller. It can read from and write to any host path the caller supplies; it is not limited to the OpenClaw workspace.
- The `/root/.openclaw/workspace/...` paths in the command examples show where the skill entrypoint lives. They do not restrict which files the skill can access.
- The `tts` command uses `edge-tts`, which sends the input text to an external text-to-speech service over the network to generate audio.
- Do not use `tts` with sensitive or private text unless you are comfortable sending that text off-host.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The constant sets the default text-to-speech voice to "en-US-AriaNeural", which imposes a specific language/locale choice in natural-language behavior. In this file there is no indication that users can opt into a different locale or that the US English default is justified as a region-specific requirement.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

This code performs filesystem changes by creating a converted output file and potentially renaming it into the requested destination, but there is no confirmation prompt, logging, or explicit user-facing disclosure in the code. The brief docstring states the function converts documents, but it does not warn that it will write to the specified output path and may overwrite expectations about file placement.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

_cmd_ocr uses OCR_DEFAULT_LANG whenever --lang is not provided, which imposes a locale/language choice by default. The file does not show an explicit user choice mechanism or justification for that default as a region-specific constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

_cmd_tts falls back to TTS_DEFAULT_VOICE, and the usage example shows a locale-specific voice (en-US-AriaNeural), indicating the skill may force a language/locale choice unless the user overrides it. This file does not present that as an explicit opt-in or explain why a fixed locale default is appropriate.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.