Back to skill

Security audit

pdf-extraction

Security checks for vulnerabilities and agentic risk

Overview

This is a local PDF text/OCR extraction skill with reasonable purpose fit and no evidence of hidden data exfiltration or malicious behavior.

Install in a virtual environment, prefer a pinned tag or commit instead of mutable main, and only use sudo for Tesseract if you trust the package source. Run it only on PDFs you are authorized to process, choose output paths carefully to avoid overwriting files, and keep OCR DPI/page ranges reasonable for large or untrusted PDFs.

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)

T09 · Insecure Skill Coding Practices

Warning
Location
pdf_extract/cli.py:94
Finding
Unbounded OCR DPI Enables Resource-Exhaustion Denial of Service<![CDATA[ ## Vulnerability Details **File Location**: `pdf_extract/cli.py:94-99`; data reaches the OCR operation at `pdf_extract/extract.py:169-178` **Vulnerability Type**: Unrestricted resource consumption through an unvalidated rendering parameter **Risk Level**: Medium ### Vulnerable Code ```python parser.add_argument( "--ocr-dpi", type=int, default=200, help="OCR render DPI (default: 200)", ) ``` The value is passed directly into full-page OCR rendering: ```python textpage = page.get_textpage_ocr( flags=0, language=language, dpi=dpi, full=True, tessdata=None, ) text = page.get_text("text", textpage=textpage) or "" return text.strip() ``` ### Technical Analysis The `--ocr-dpi` argument accepts any integer and has no upper bound. PyMuPDF uses this value when rendering the entire PDF page for Tesseract OCR. Rendering cost and image memory consumption increase approximately with the square of the resolution increase because both image dimensions grow with DPI. An excessively large DPI can therefore create extremely large intermediate images and consume substantial CPU time and memory. The problem is amplified because the application imposes no document-size, page-count, memory, or OCR execution-time limits. Forced OCR mode can apply the expensive operation to every selected page. Although exploitation requires the ability to influence command-line arguments or invoke the extraction functionality through an integrating Agent, no elevated privileges are required. ### Attack Path 1. An attacker supplies or identifies a PDF that the Agent will process. 2. The attacker induces the Agent or an integrating service to invoke the CLI with an extreme value, for example: ```bash pdf-extract document.pdf --mode ocr --ocr-dpi 100000 ``` 3. The CLI accepts the integer without validation. 4. The value is passed to `page.get_textpage_ocr(..., dpi=100000, full=True)`. 5. PyMuPDF attempts to render a full-page image at the ...[truncated 892 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Enforce explicit lower and upper bounds immediately after argument parsing. For example: ```python MIN_OCR_DPI = 72 MAX_OCR_DPI = 600 if not MIN_OCR_DPI <= args.ocr_dpi <= MAX_OCR_DPI: parser.error( f"--ocr-dpi must be between {MIN_OCR_DPI} and {MAX_OCR_DPI}" ) ``` 2. Repeat validation inside `extract_pdf` or `_extract_ocr_text` so library callers cannot bypass CLI validation. 3. Limit the maximum number of pages processed in one operation, particularly when OCR is enabled. 4. Inspect page dimensions before rendering and reject requests whose calculated pixel count exceeds a safe threshold. 5. Execute OCR under operating-system memory, CPU, and wall-clock limits. In a service environment, isolate OCR in a restricted worker process or container that can be terminated safely. 6. Apply input file-size limits and configure retry systems not to retry deterministic resource-limit failures automatically. 7. Add tests for negative, zero, and extreme DPI values and verify that they are rejected before opening or rendering the PDF. ]]>

T08 · Insecure Dependencies

Warning
Location
README.md:34
Finding
Mutable and Unconstrained Installation Sources Reduce Supply-Chain Integrity<![CDATA[ ## Vulnerability Details **File Location**: `README.md:34-39`; related unconstrained dependencies at `pyproject.toml:1-3` and `pyproject.toml:30-35` **Vulnerability Type**: Mutable package source and open-ended dependency resolution **Risk Level**: Medium ### Vulnerable Code The installation documentation recommends installing directly from the mutable default branch: ```bash # 最新 main pip install "git+https://github.com/alex-ht/pdf-extraction.git" # 指定版本 tag pip install "git+https://github.com/alex-ht/pdf-extraction.git@v1.0.0" ``` Build and runtime dependencies are specified only with lower bounds: ```toml [build-system] requires = ["setuptools>=68", "wheel"] build-backend = "setuptools.build_meta" ``` ```toml dependencies = [ "pdfplumber>=0.11", "pymupdf>=1.24", "Pillow>=10", ] ``` ### Technical Analysis Installing from a Git repository without an immutable commit identifier causes the effective package contents to depend on the state of the repository at installation time. Code installed in the future may differ from the artifact covered by this audit. The version tag example is safer than the mutable branch but is still not cryptographically verified by the instructions. The runtime and build dependencies also have no upper bounds, lock file, or hashes, allowing future releases to be selected automatically. Python package installation can execute build-backend code during the build process, while installed package code executes with the privileges of the invoking user. Consequently, compromise of the upstream repository, a dependency account, release infrastructure, or package distribution channel could introduce code that was not present during this review. This finding does not establish that any current dependency is malicious. It identifies a supply-chain integrity weakness that permits unaudited future code to enter installations. ### Attack Path 1. An attacker compromises the upstream Git repository, a maintainer ac ...[truncated 1419 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not recommend installation from an unqualified mutable branch. Prefer an immutable commit identifier: ```bash pip install \ "git+https://github.com/alex-ht/pdf-extraction.git@<full-commit-sha>" ``` 2. Prefer signed and verified release artifacts from a trusted package registry. 3. Publish cryptographic hashes and use hash-verified installation where practical: ```bash pip install --require-hashes -r requirements.txt ``` 4. Maintain a deployment lock file or constraints file containing reviewed versions of all direct and transitive dependencies. 5. Add compatible upper bounds where appropriate and test dependency upgrades before releasing them. 6. Pin or constrain build-system dependencies because build dependencies execute during package construction. 7. Protect source and package-publishing accounts with multifactor authentication, branch protection, restricted release permissions, and signed tags or commits. 8. Run installation without administrative privileges and inside an isolated virtual environment or container. 9. Add automated dependency vulnerability scanning and provenance verification to the release process. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (14)

Ae1

High
Category
analysis-evasion
Content
- Python 3.10+: `pdfplumber`, `pymupdf`, `Pillow` (see `pyproject.toml`)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
```bash
# Ubuntu / Debian
sudo apt install tesseract-ocr tesseract-ocr-eng
# 繁中可選:
# sudo apt install tesseract-ocr-chi-tra
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
```bash
# Ubuntu / Debian
sudo apt install tesseract-ocr tesseract-ocr-eng
# 繁中可選:
# sudo apt install tesseract-ocr-chi-tra
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Ubuntu / Debian
sudo apt install tesseract-ocr tesseract-ocr-eng
# 繁中可選:
# sudo apt install tesseract-ocr-chi-tra

# macOS
# brew install tesseract
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Ubuntu / Debian
sudo apt install tesseract-ocr tesseract-ocr-eng
# 繁中可選:
# sudo apt install tesseract-ocr-chi-tra

# macOS
# brew install tesseract
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The skill documentation appears to force a specific language/locale for instructions and usage details, with no alternative language option or explicit user opt-in. Under the stated policy, language constraints should either be optional or clearly justified as region-specific.

Missing User Warnings

Low
Confidence
83% confidence
Finding
This markdown file documents a skill that reads PDFs, extracts their text, and can emit the contents to stdout or output files. Because PDFs often contain sensitive personal or business information, the usage section should include a user-facing warning about handling confidential content, especially when OCR is applied to scanned documents.

Missing User Warnings

Low
Confidence
92% confidence
Finding
The skill instructs users and agents to write extracted content to paths via `-o out.txt`, `-o out.md`, and `-o out.json` without warning about overwriting existing files or choosing safe destinations. In agentic contexts, this can lead to accidental clobbering of user data if filenames are reused or derived unsafely from prompts.

Unverifiable Dependency: setuptools has 10 known advisory(ies) (CVE-2013-1633 (Setuptools vulnerable to Man-in-the-middle attacks); CVE-2025-47273 (setuptools has a path traversal vulnerability in PackageIndex.download that lead); CVE-2024-6345 (setuptools vulnerable to Command Injection via package URL) +7 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.

Unverifiable Dependency: wheel has 4 known advisory(ies) (CVE-2026-24049 (Wheel Affected by Arbitrary File Permission Modification via Path Traversal in w); CVE-2022-40898 (pypa/wheel vulnerable to Regular Expression denial of service (ReDoS)); CVE-2022-40898 (An issue discovered in Python Packaging Authority (PyPA) Wheel 0.37.1 and earlie) +1 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.

Unverifiable Dependency: pymupdf has 2 known advisory(ies) (CVE-2026-3029 (PyMuPDF has a path traversal in _main_.py); CVE-2026-3029 (PyMuPDF has a path traversal in _main_.py)), 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.

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.

Unverifiable Dependency: pytest has 2 known advisory(ies) (CVE-2025-71176 (pytest has vulnerable tmpdir handling); CVE-2025-71176 (pytest has vulnerable tmpdir handling)), 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.