Back to skill

Security audit

docs-pdf

Security checks for vulnerabilities and agentic risk

Overview

This PDF skill appears to perform PDF tasks, but its setup asks users to run powerful, unpinned system and package-manager installs that deserve review before installation.

Install only in an isolated virtual environment or container, avoid --break-system-packages where possible, pin dependencies before use, and treat sudo package installation as an administrator setup step. Run batch, OCR, extraction, metadata, and decrypt operations only on PDFs you own or are authorized to process, and review where generated text/PDF/report files are saved.

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 (2)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:78
Finding
Unpinned Third-Party Dependencies and Bypassed Environment Protections<![CDATA[ ## Vulnerability Details **File Locations**: - `SKILL.md:78-89` - `SKILL.md:94-105` - `FORMS.md:82-87` **Vulnerability Type**: Unpinned dependencies installed directly from public package registries **Risk Level**: Medium ### Vulnerable Code `SKILL.md:78-89`: ```bash # Python libraries pip install pypdf pdfplumber reportlab pdf2image pytesseract Pillow --break-system-packages # System tools sudo apt-get install -y poppler-utils tesseract-ocr qpdf # For Chinese OCR sudo apt-get install -y tesseract-ocr-chi-sim tesseract-ocr-chi-tra # Node.js (form filling) npm install pdf-lib ``` `SKILL.md:94-105`: ```bash # System tools (required for OCR and CLI operations) brew install qpdf poppler tesseract # IMPORTANT: Language packs must be installed separately for non-English OCR brew install tesseract-lang # Python libraries pip install pypdf pdfplumber reportlab pdf2image pytesseract Pillow --break-system-packages # Node.js (form filling) npm install pdf-lib ``` `FORMS.md:82-87`: ```markdown ### Setup ```bash npm install pdf-lib ``` ``` ### Technical Analysis The installation commands do not pin dependency versions and do not verify package integrity through hashes or lockfiles. Consequently, the exact code installed depends on the package versions returned by the registry at installation time. The Python installation also uses `--break-system-packages`, which bypasses protections intended to prevent package managers from modifying an externally managed Python environment. This can cause dependency replacement or conflicts at the host level rather than containing changes within a project-specific virtual environment. This does not establish that any currently named package is malicious. The security weakness is that installation is non-reproducible and trusts future registry responses without integrity verification. If a dependency release or registry account is compromised, installation-time scripts or imported package code could execute with t ...[truncated 1416 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin every Python and Node.js dependency to a reviewed version. 2. Provide a Python requirements lockfile with cryptographic hashes, for example: ```text pypdf==X.Y.Z --hash=sha256:REVIEWED_HASH pdfplumber==X.Y.Z --hash=sha256:REVIEWED_HASH ``` 3. Install Python dependencies in an isolated virtual environment: ```bash python3 -m venv .venv . .venv/bin/activate python -m pip install --require-hashes -r requirements.txt ``` 4. Remove `--break-system-packages` from the recommended installation process. 5. Commit `package-lock.json` and recommend `npm ci` instead of an unconstrained `npm install`. 6. Use trusted registry configuration and avoid silently falling back to unapproved package indexes. 7. Periodically scan locked dependencies for known vulnerabilities and review updates before changing pinned versions. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
SKILL.md:217
Finding
PDF Password Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Locations**: - `SKILL.md:217-219` - `references/security.md:137-139` **Vulnerability Type**: Plaintext sensitive data in process arguments and shell history **Risk Level**: Low ### Vulnerable Code `SKILL.md:217-219`: ```bash # Remove password qpdf --password=secret --decrypt locked.pdf unlocked.pdf ``` `references/security.md:137-139`: ```python # CLI (qpdf) # qpdf --password=secret --decrypt locked.pdf unlocked.pdf ``` ### Technical Analysis The examples instruct users to place the PDF password directly in the qpdf command line. When a real password replaces `secret`, it may become visible through: - Shell history files. - Process argument listings while qpdf is running. - Terminal session recordings. - CI/CD logs or command tracing. - Wrapper scripts and automation logs. - System auditing facilities that record process arguments. Although command-line arguments are not necessarily visible to every user on every operating system, they should not be treated as a secure secret-transport mechanism. The issue is limited to confidentiality of the supplied PDF password; no command injection is present because this is a documentation example rather than a shell constructed by the Python scripts. ### Attack Path 1. A user substitutes a sensitive PDF password for `secret`. 2. The user executes the documented qpdf command. 3. The plaintext password is stored in shell history, captured in logs, or temporarily exposed through process inspection. 4. An attacker or another local account with access to that data retrieves the password. 5. The attacker uses the recovered password to decrypt the protected PDF or other documents that reuse the same password. ### Impact Assessment Successful exploitation discloses the PDF password. The attacker may then access the protected document and any other documents secured with the same credential. The issue does not independently grant operating-system privileges or remote code execu ...[truncated 169 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not place real passwords directly in command-line arguments. 2. Prefer an interactive password prompt when supported. 3. If the installed qpdf version supports reading a password from a file or file descriptor, use a temporary, user-readable-only secret file or protected descriptor. 4. Ensure any password file is created with restrictive permissions, such as mode `0600`, and securely removed after use. 5. Disable command echoing and secret logging in automation environments. 6. Document that environment variables may also leak through process inspection or diagnostic output and should not be presented as universally secure. 7. Advise users to clear any existing shell-history entries containing passwords and to avoid password reuse across documents. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
Findings (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The description claims a broad 'anything with PDF files' skill, but the supplied code chunk is a narrow batch-processing script supporting only merge, split, rotate, and watermark operations. This is a material description-to-behavior mismatch because many prominently declared capabilities are absent from the code. There is no evidence of text extraction, OCR, encryption, metadata viewing, conversions, comparison, repair, form handling, or font listing. The implemented behavior is PDF-related and consistent with part of the description, but the declared scope substantially overstates the actual functionality.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This is a description-behavior mismatch because the declared purpose represents the skill as a universal PDF tool with many operations and very broad triggers, while the supplied code performs only one specific function: comparing the extracted text of two PDF files and producing a diff report. Although PDF comparison is one of the declared examples, the overall description and trigger conditions materially overstate the skill’s actual scope and would cause invocation in many unrelated PDF tasks the code cannot handle. There is no evidence of undeclared sensitive behavior; the mismatch is primarily that the declared primary purpose is far broader than the implemented behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This is a clear description-behavior mismatch. The code does not implement a general-purpose PDF skill; it only inspects PDF resource dictionaries to enumerate fonts. It cannot merge, split, rotate, watermark, create, fill, encrypt, OCR, compress, convert, compare, repair, extract text/tables/images, or perform most other declared functions. While 'listing fonts' is one item included in the description, the declared purpose materially overstates the skill's scope and would cause it to trigger for many unrelated PDF tasks that this code cannot handle. There are no concerning undeclared side effects beyond reading local PDF files and printing/serializing results.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This is a description-behavior mismatch. While merging PDFs is one of the declared capabilities, the description represents the skill as handling virtually all PDF-related tasks and triggering on any PDF operation. The supplied code chunk only merges multiple PDFs into one output file, using pypdf's PdfReader/PdfWriter and simple path resolution. There is no implementation for the many other declared PDF operations, and the trigger guidance is materially broader than what this code can fulfill. This is not an issue of over-declared permissions, but of overstated functionality and unrelated trigger scope relative to the actual code.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This is a description-behavior mismatch because the declared purpose presents a comprehensive PDF toolkit, while the supplied code only performs one specific function: OCR text extraction from scanned PDFs to plain text files. OCR is one item in the declared list, but the overall description materially overstates the implemented functionality and trigger scope. There is no evidence of PDF merging, splitting, editing, form filling, encryption, metadata inspection, image extraction, conversion, repair, or similar operations. The code's primary purpose is much narrower than declared.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill documents shell commands, file reads, and file writes but does not declare any explicit tool scope or permissions boundary. In an agent environment, that omission can allow the skill to be invoked with broader capabilities than necessary, increasing the chance of unintended file access or command execution.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The trigger condition says to use the skill for essentially any mention of PDFs, including broad file creation, editing, or extraction contexts. In an agent system, that can cause the skill to activate in situations where shell commands, file modifications, OCR tooling, or repair scripts are unnecessary, increasing the chance of unsafe actions on user files.

Unrestricted Tool Access

Medium
Category
Excessive Agency
Content
| 🔧 Repair corrupted PDF | `scripts/repair_pdf.py` | `python scripts/repair_pdf.py broken.pdf -o fixed.pdf` |
| 🔤 List fonts | `scripts/list_fonts.py` | `python scripts/list_fonts.py input.pdf` |

> 💡 Run any script with `--help` to see all available options.

---
Confidence
84% confidence
Finding
Telling the agent to 'run any script' without restrictions encourages arbitrary execution of local helper scripts. In a skill context where scripts can read/write files and invoke external tools, that broad execution guidance increases the risk of running unsafe or unintended code paths.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
pip install pypdf pdfplumber reportlab pdf2image pytesseract Pillow --break-system-packages

# System tools
sudo apt-get install -y poppler-utils tesseract-ocr qpdf

# For Chinese OCR
sudo apt-get install -y tesseract-ocr-chi-sim tesseract-ocr-chi-tra
Confidence
89% confidence
Finding
The documentation instructs use of `sudo apt-get install`, which requires elevated privileges and can change the host system outside the skill's immediate task. In an agent or sandboxed environment, encouraging root-level package installation is risky because it can alter system state, expand available tooling, and bypass least-privilege expectations.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
sudo apt-get install -y poppler-utils tesseract-ocr qpdf

# For Chinese OCR
sudo apt-get install -y tesseract-ocr-chi-sim tesseract-ocr-chi-tra

# Node.js (form filling)
npm install pdf-lib
Confidence
89% confidence
Finding
This second `sudo` instruction extends the same problem to additional OCR language packages, again requiring privileged system modification. Even when intended for setup only, embedding root-level commands in a skill raises the chance of unsafe execution in environments where the agent should not escalate privileges.

Unrestricted Tool Access

Medium
Category
Excessive Agency
Content
| `scripts/repair_pdf.py` | Attempt to repair corrupted PDF files |
| `scripts/list_fonts.py` | List all fonts used in a PDF |

Run any script with `--help` to see its options.

---
Confidence
84% confidence
Finding
This repeated instruction again normalizes unrestricted script execution rather than least-privilege task selection. If the repository later includes unsafe or compromised scripts, the skill text would encourage their use without review.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
This markdown file includes code that writes OCR output to disk, which can persist sensitive contents from scanned PDFs, but the surrounding documentation does not warn users about saving potentially confidential extracted text. Under the markdown-file criteria for SQP-2, descriptions that omit warnings about behaviors affecting user data or privacy should be flagged.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
```bash
# Linux (Ubuntu/Debian)
sudo apt-get install tesseract-ocr-chi-sim tesseract-ocr-chi-tra tesseract-ocr-jpn

# macOS (Homebrew) — installs ALL language packs at once
brew install tesseract-lang
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The batch script processes every PDF in a directory and writes corresponding .txt files, which can affect large amounts of user data, but the markdown description provides no warning about this broad file-processing behavior. For markdown files, SQP-2 applies when potentially privacy- or data-impacting behavior is described without user-facing warning.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The document includes explicit instructions and code to decrypt PDFs and remove password protection, but provides no guardrails about authorization, ownership, or legal/ethical constraints. In a general-purpose PDF manipulation skill, this can normalize or facilitate bypassing document protections on files the user may not be authorized to unlock.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def qpdf_optimize(src: Path, dst: Path) -> bool:
    """Use qpdf to linearize and optimize object streams."""
    try:
        subprocess.run(
            ["qpdf", "--linearize",
             "--object-streams=generate",
             "--compress-streams=y",
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
# Try qpdf check
    if has_qpdf():
        try:
            proc = subprocess.run(
                ["qpdf", "--check", str(path)],
                capture_output=True, text=True,
            )
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
# More aggressive: attempt to recover even with severe errors
            cmd = ["qpdf", "--qdf", "--object-streams=disable", str(src), str(dst)]

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

        if proc.returncode in (0, 3):  # 0=ok, 3=warnings but succeeded
            if proc.stderr:
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
The macOS warning is written in Chinese ('macOS 注意') even though the surrounding document is primarily in English, and the file does not state that the skill is region-specific or ask the user to opt into that locale. This can violate a language/locale consistency policy by imposing a language choice without user selection.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
Several bullet points and the limitations table switch to Chinese without explaining that the skill targets Chinese-speaking users or offering an English alternative. Because the rest of the skill is in English, this creates an undocumented forced locale change in the natural-language instructions.

Missing User Warnings

Low
Confidence
87% confidence
Finding
This markdown file includes executable examples that create files such as "output.pdf" via `SimpleDocTemplate(...); doc.build(story)` and later `drawing.pdf` via `canvas.Canvas(...)` and `c.save()`. The document presents these snippets as ready-to-run instructions but does not warn users that running them will write files to disk, which fits the markdown-specific missing-warning criterion for user data/system-affecting behavior.

Natural-Language Policy Violations

Low
Confidence
86% confidence
Finding
The macOS warning is presented only in Chinese while the rest of the document is primarily in English, which imposes a language-specific instruction without opt-in or explanation. SQP-3 covers natural-language policy issues where a skill forces a specific language or locale without user choice.

Missing User Warnings

Low
Confidence
88% confidence
Finding
This code reads author, creator, subject, and document dates from the PDF and includes them in terminal and JSON output. Although the module docstring describes metadata extraction, there is no explicit user-facing warning that sensitive document metadata may be displayed or exported, which is relevant because SQP-2 covers operations affecting user privacy/data disclosure.

Static analysis

No suspicious patterns detected.