Back to skill

Security audit

Printer

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent printer skill that runs expected CUPS print commands with visible file-path safeguards and no evidence of credential theft, persistence, or hidden behavior.

Install this only on a machine where you are comfortable allowing an agent to submit CUPS print jobs and read printer PPD metadata. Prefer a virtual environment, use a reviewed/pinned Pillow version, and pass only CUPS options you understand.

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

Note
Location
pyproject.toml:6
Finding
Unpinned Pillow Dependency Creates Mutable Supply-Chain Exposure## Vulnerability Details **File Location**: `pyproject.toml:6-8`, `scripts/print.py:2-5`, `SETUP.md:23-26` **Vulnerability Type**: Unlocked third-party dependency **Risk Level**: Low ### Vulnerable Code `pyproject.toml:6-8`: ```toml dependencies = [ "pillow>=10.0.0", ] ``` `scripts/print.py:2-5`: ```python # /// script # requires-python = ">=3.10" # dependencies = ["Pillow"] # /// ``` `SETUP.md:23-26`: ```bash # Verify setup python3 {baseDir}/scripts/print.py list # Install Pillow (only needed for image printing) pip install Pillow ``` ### Technical Analysis The project declares Pillow inconsistently and without a reproducible dependency lock: - `pyproject.toml` accepts every Pillow release at or above version 10.0.0. - The inline script metadata permits any version of Pillow. - The setup documentation instructs users to install the latest version available from pip. - No lock file, integrity hash, or index restriction is supplied. Consequently, two installations performed at different times can execute different dependency code even though the audited project files have not changed. This does not establish that the current Pillow package is malicious; the exposure arises because future or otherwise substituted artifacts are trusted without version and integrity verification. ### Attack Path 1. An attacker compromises an eligible future Pillow release, its distribution account, the configured package index, or the victim's package-resolution path. 2. A user follows `SETUP.md` and runs `pip install Pillow`, or a script-aware runner resolves the inline `dependencies = ["Pillow"]` declaration. 3. Because no exact version or artifact hash is required, pip accepts the attacker-controlled eligible artifact. 4. Malicious package code can execute during installation or when `scripts/print.py` imports Pillow for image conversion. 5. The payload runs with the privileges of th ...[truncated 781 chars]
Remediation
## Remediation Suggestions 1. Pin Pillow to one reviewed exact version consistently in every dependency declaration, for example: ```toml dependencies = [ "pillow==<reviewed-version>", ] ``` 2. Update the inline script metadata and setup documentation to use the same exact version. 3. Generate and commit a dependency lock file containing hashes for approved distributions. 4. Install with integrity enforcement, such as: ```bash python3 -m pip install --require-hashes -r requirements.txt ``` 5. Restrict installation to the intended package index and use a controlled mirror where practical. 6. Review and update the pinned version through a documented dependency-update process that includes vulnerability scanning, provenance checks, and functional testing. 7. Prefer installation in an isolated virtual environment under a non-privileged account.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (8)

Credential Access

High
Category
Privilege Escalation
Content
Security checks:
      1. Resolve symlinks, then verify the *real* path is inside an
         allowed root (workspace or /tmp). This lets symlinks within
         the workspace work while blocking ``ln -s ~/.ssh/id_rsa x.pdf``.
      2. Verify the *resolved* file has a printable extension.
    """
    if not file_path.exists():
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill exposes shell-capable behavior and access to local files/environment through its documented entry point and required binaries, but it does not declare any tool scope restrictions such as explicit permissions or allowed-tools. This creates an avoidable trust gap: an agent may invoke filesystem and shell operations more broadly than reviewers or policy expect, increasing the risk of unintended command execution or access to sensitive local resources.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def get_default_printer():
    """Get the system default printer name."""
    result = subprocess.run(['lpstat', '-d'], capture_output=True, text=True)
    if result.returncode == 0:
        for line in result.stdout.splitlines():
            if line.startswith("system default destination:"):
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
for opt in (extra_options or []):
        cmd.extend(['-o', opt])

    result = subprocess.run(cmd, capture_output=True, text=True)

    if result.returncode == 0:
        output = result.stdout.strip()
Confidence
87% confidence
Finding
Although `subprocess.run` is used safely without a shell, the code forwards user-supplied `-o/--option` values directly to `lp`. CUPS options can alter backend behavior, trigger network access, or weaken intended safety constraints, so this creates an argument-injection style risk into the printing subsystem rather than shell injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def cmd_list(args):
    """List available printers."""
    result = subprocess.run(['lpstat', '-p', '-d'], capture_output=True, text=True)
    if result.returncode != 0:
        if args.json:
            print(json_mod.dumps({"error": "Could not list printers"}))
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
print(f"Error: {msg}", file=sys.stderr)
        return 1

    result = subprocess.run(['lpoptions', '-p', printer, '-l'], capture_output=True, text=True)
    if result.returncode != 0:
        msg = f"Could not get options for {printer}"
        if args.json:
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Description-Behavior Mismatch

Low
Confidence
89% confidence
Finding
The manifest describes a general-purpose printer skill for any CUPS printer, but the package description in the code metadata says it prints to an HP Color LaserJet printer. That creates a semantic mismatch about the intended device scope of the skill.

Unverifiable Dependency: pillow has 16 known advisory(ies) (CVE-2016-2533 (Pillow buffer overflow in ImagingPcdDecode); CVE-2023-50447 (Arbitrary Code Execution in Pillow); CVE-2021-27922 (Pillow Uncontrolled Resource Consumption) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Static analysis

No suspicious patterns detected.