T08 · Insecure Dependencies
Warning
- Location
- scripts/export_long_image.py:14
- Finding
- Automatic Installation of Unpinned Runtime Dependencies<![CDATA[ ## Vulnerability Details **File Location**: `scripts/export_long_image.py:14-31, 88-114`; `scripts/render_markdown_mobile_long_image.py:631-664` **Vulnerability Type**: Uncontrolled installation of mutable third-party dependencies **Risk Level**: Medium ### Vulnerable Code From `scripts/export_long_image.py`: ```python def _run_install(package_name: str) -> None: ensure_commands = [ [sys.executable, "-m", "ensurepip", "--upgrade"], ] install_commands = [ [sys.executable, "-m", "pip", "install", package_name], ] uv_path = shutil.which("uv") if uv_path: install_commands.append([uv_path, "pip", "install", "--python", sys.executable, package_name]) for ensure_command in ensure_commands: subprocess.run(ensure_command, check=False) last_error: Exception | None = None for command in install_commands: try: subprocess.run(command, check=True) return except Exception as exc: # noqa: BLE001 last_error = exc if last_error is not None: raise last_error ``` ```python def ensure_playwright_module() -> None: try: importlib.import_module("playwright.sync_api") return except ImportError: pass _run_install("playwright") importlib.import_module("playwright.sync_api") def install_playwright_browser() -> None: subprocess.run( [sys.executable, "-m", "playwright", "install", "chromium"], check=True, ) def ensure_pillow() -> None: try: importlib.import_module("PIL.Image") return except ImportError: pass _run_install("pillow") importlib.import_module("PIL.Image") ``` The renderer contains an equivalent installer in `scripts/render_markdown_mobile_long_image.py`: ```python def _run_install(package_name: str) -> None: ensure_commands = [ [sys.executable, "-m", "ensurepip", "--upgrade"], ] install_commands = [ ...[truncated 3013 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove automatic dependency installation from the document-conversion path. 2. Declare exact dependency versions in a project manifest and generate a lockfile. 3. Require hashes for downloaded distributions, for example through a hash-locked requirements file. 4. Install dependencies during a separate, explicit setup phase rather than during content processing. 5. Use an isolated virtual environment or container with only the required packages. 6. Restrict installation to an explicitly trusted package index and prevent inherited alternate-index configuration where feasible. 7. Pin the Playwright browser build and provision it during installation or image construction. 8. If a dependency is unavailable at runtime, fail safely with installation instructions rather than modifying the environment. 9. Run dependency scanning and signature or provenance verification in the release pipeline. ]]>
