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. ]]>
