Back to skill

Security audit

pdf-compress-tool

Security checks for vulnerabilities and agentic risk

Overview

This PDF compression skill does what it claims, but it automatically installs an unpinned Python package during normal use without a consent gate.

Review before installing, especially in managed or sensitive environments. Use only in an isolated virtual environment or container, preinstall reviewed/pinned dependencies yourself, and avoid letting the skill run pip automatically on systems with sensitive files or credentials.

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
compress_pdf.py:153
Finding

Automatic Installation of an Unpinned Runtime Dependency

Content
View full analysis

Vulnerability Details

File Location: compress_pdf.py, lines 153-159
Vulnerability Type: Unpinned automatic third-party dependency installation
Risk Level: Medium

Vulnerable Code

python
except ImportError:
    print("  pikepdf not installed, attempting to install...")
    subprocess.run(
        [sys.executable, "-m", "pip", "install", "pikepdf"],
        check=True, capture_output=True,
    )
    import pikepdf
    return pikepdf

Technical Analysis

When pikepdf is unavailable, _ensure_pikepdf() automatically invokes pip and installs the latest package version resolved under the user's current Python and package-index configuration. The dependency is not constrained by an exact version, lockfile, cryptographic hash, or verified artifact source.

Although the subprocess call safely uses an argument list and does not expose a shell-command-injection issue, it introduces a supply-chain trust boundary during ordinary PDF processing. The code eventually imported is mutable and may differ from what was reviewed. Package installation can also execute package build or installation logic with the privileges of the running process.

The behavior is explicitly documented in SKILL.md, so it is not concealed; nevertheless, documentation does not mitigate the dependency integrity risk.

Attack Path

  1. A user runs the PDF compression tool in an environment where pikepdf is not installed.
  2. PDF processing calls _ensure_pikepdf().
  3. The function executes python -m pip install pikepdf without a version or hash constraint.
  4. Pip resolves the package and transitive dependencies from the environment's configured index or mirror.
  5. If the upstream release, index, mirror, dependency chain, or local pip configuration is compromised, attacker-controlled package content is downloaded and installed.
  6. Malicious installation logic or imported package code executes under the identity and permissions of the user running the tool.

...[truncated 576 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove automatic package installation from runtime application logic. If pikepdf is missing, terminate safely and display explicit installation instructions.
  2. Declare dependencies in a version-controlled dependency manifest and pin pikepdf and its transitive dependencies to reviewed versions.
  3. Use a lockfile or a hash-validated requirements file, such as pip's --require-hashes, to verify artifact integrity.
  4. Install dependencies during a controlled deployment or setup phase rather than while processing user documents.
  5. Use an isolated virtual environment or container with least-privilege permissions.
  6. Restrict installation to a trusted package repository or approved internal mirror and validate its transport and access configuration.
  7. Require explicit user or administrator approval before any dependency installation.
  8. Add dependency vulnerability and provenance scanning to the release process.

A safer runtime pattern is:

python
except ImportError as exc:
    raise RuntimeError(
        "pikepdf is required. Install the reviewed, pinned dependency "
        "in an isolated environment before running this tool."
    ) from exc
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (16)

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Runtime pip installation is an unjustified high-risk capability for this skill because it can fetch and execute code from external package sources during normal use. In a security-sensitive or automated agent environment, that creates a supply-chain and unauthorized-environment-modification risk disproportionate to the task.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill advertises behavior that writes files and invokes shell-based tooling, but it does not declare any explicit tool scope such as permissions or allowed-tools. That creates a trust and policy gap: an agent may execute filesystem and subprocess actions that are broader than reviewers or runtime policy expect, increasing the risk of unintended command execution, file overwrite, or use of unsafe external binaries.

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 · SKILL.md (reported line 108)May include surrounding context.

md
return f"brew install {pkg}"
    elif s == "Linux":
        if shutil.which("apt-get"):
            return f"sudo apt-get install {pkg}"
        elif shutil.which("dnf"):
            return f"sudo dnf install {pkg}"
        elif shutil.which("yum"):

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

md
return f"brew install {pkg}"
    elif s == "Linux":
        if shutil.which("apt-get"):
            return f"sudo apt-get install {pkg}"
        elif shutil.which("dnf"):
            return f"sudo dnf install {pkg}"
        elif shutil.which("yum"):

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 · compress_pdf.py (reported line 60)May include surrounding context.

python
return f"brew install {pkg}"
    elif s == "Linux":
        if shutil.which("apt-get"):
            return f"sudo apt-get install {pkg}"
        elif shutil.which("dnf"):
            return f"sudo dnf install {pkg}"
        elif shutil.which("yum"):

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 · compress_pdf.py (reported line 62)May include surrounding context.

python
return f"brew install {pkg}"
    elif s == "Linux":
        if shutil.which("apt-get"):
            return f"sudo apt-get install {pkg}"
        elif shutil.which("dnf"):
            return f"sudo dnf install {pkg}"
        elif shutil.which("yum"):

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 · compress_pdf.py (reported line 64)May include surrounding context.

python
return f"brew install {pkg}"
    elif s == "Linux":
        if shutil.which("apt-get"):
            return f"sudo apt-get install {pkg}"
        elif shutil.which("dnf"):
            return f"sudo dnf install {pkg}"
        elif shutil.which("yum"):

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 · compress_pdf.py (reported line 66)May include surrounding context.

python
return f"brew install {pkg}"
    elif s == "Linux":
        if shutil.which("apt-get"):
            return f"sudo apt-get install {pkg}"
        elif shutil.which("dnf"):
            return f"sudo dnf install {pkg}"
        elif shutil.which("yum"):

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 · compress_pdf.py (reported line 67)May include surrounding context.

python
return f"brew install {pkg}"
    elif s == "Linux":
        if shutil.which("apt-get"):
            return f"sudo apt-get install {pkg}"
        elif shutil.which("dnf"):
            return f"sudo dnf install {pkg}"
        elif shutil.which("yum"):

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 · compress_pdf.py (reported line 125)May include surrounding context.

python
tools["gs"] = gs_cmd
    if gs_cmd:
        try:
            result = subprocess.run(
                [gs_cmd, "--version"], capture_output=True, text=True, timeout=5
            )
            gs_ver = result.stdout.strip()

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 · compress_pdf.py (reported line 140)May include surrounding context.

python
tools["qpdf"] = qpdf_cmd
    if qpdf_cmd:
        try:
            result = subprocess.run(
                [qpdf_cmd, "--version"], capture_output=True, text=True, timeout=5
            )
            qpdf_ver = result.stdout.strip().split("\n")[0]

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Auto-installing pikepdf expands the skill's capabilities from document processing to software modification of the host environment. That mismatch matters in an agent-skill context because users may authorize PDF compression without expecting package installation, network access, or persistent system changes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill installs software automatically after only printing a status message, without requiring prior confirmation. That can surprise users, violate least astonishment, and in managed environments trigger unauthorized network access or host changes.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
97% confidence
Finding

This code automatically installs a Python package at runtime with pip, which gives the skill network/package-management capability beyond simple PDF compression. If package sources are tampered with, dependency resolution is poisoned, or the environment is sensitive, this can result in unexpected code execution and supply-chain compromise without explicit user approval.

Content

Scanner excerpt · compress_pdf.py (reported line 169)May include surrounding context.

python
return pikepdf
    except ImportError:
        print("  pikepdf not installed, attempting to install...")
        subprocess.run(
            [sys.executable, "-m", "pip", "install", "pikepdf"],
            check=True, capture_output=True,
        )

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 · compress_pdf.py (reported line 263)May include surrounding context.

python
args.extend([f"-sOutputFile={output_path}", input_path])

    try:
        subprocess.run(args, check=True, capture_output=True, text=True)
        return True
    except subprocess.CalledProcessError:
        return False

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 · compress_pdf.py (reported line 276)May include surrounding context.

python
return False

    try:
        subprocess.run(
            [
                qpdf_cmd,
                "--optimize-images",

Static analysis

No suspicious patterns detected.