T08 · Insecure Dependencies
- Location
scripts/pdf-to-word-docx.py:136- Finding
Unpinned proprietary dependency and unverified runtime model loading
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:28-31;scripts/pdf-to-word-docx.py:136-140,316-323,331-357, and534-544
Vulnerability Type: Third-party supply-chain integrity failure
Risk Level: MediumThe Skill instructs users to install a proprietary SDK without pinning an audited version or verifying the package hash:
bash pip install ComPDFKitConversionThe script also downloads a model from a mutable remote location:
python DOCUMENT_AI_MODEL_URL = "https://download.compdf.com/skills/model/documentai.model" DOCUMENT_AI_MODEL_ENV = "COMPDF_DOCUMENT_AI_MODEL" DOCUMENT_AI_MODEL_RETRY_DELAYS = (2, 5, 10) LICENSE_URL = "https://download.compdf.com/skills/license/license.xml" LICENSE_RETRY_DELAYS = (2, 5, 10)The download function writes the remote response directly to a local file without verifying a cryptographic digest or digital signature:
python def download_file(url: str, destination: Path, timeout: int = 120) -> None: destination.parent.mkdir(parents=True, exist_ok=True) with urllib.request.urlopen(url, timeout=timeout) as response, destination.open("wb") as output: while True: chunk = response.read(1024 * 1024) if not chunk: break output.write(chunk)The only content validation performed on the downloaded model is a non-empty-file check:
python def ensure_document_ai_model(scripts_dir: Path) -> Path: model_path = get_document_ai_model_path(scripts_dir) if model_path.is_file() and model_path.stat().st_size > 0: return model_path temp_path = model_path.with_suffix(model_path.suffix + ".part") last_error: Exception | None = None for attempt in range(len(DOCUMENT_AI_MODEL_RETRY_DELAYS) + 1): try: print(f"documentai.model not found, downloading from {DOCUMENT_AI_MODEL_URL}...", file=sys.stderr) if temp_p ...[truncated 5145 chars]- Remediation
View remediation
Remediation Suggestions
- Pin
ComPDFKitConversionto a specifically reviewed version rather than using an unconstrained package name. - Use a requirements or lock file containing cryptographic hashes, and install with hash enforcement, such as
pip install --require-hashes -r requirements.txt. - Obtain expected SHA-256 digests or digital signatures for
documentai.modelandlicense.xmlthrough a separately authenticated release channel. - Verify each downloaded artifact before renaming it into its final location. Delete it and fail closed if verification fails.
- Version model URLs or bind expected hashes to Skill releases so a previously audited Skill cannot silently receive a different artifact.
- Make automatic downloads opt-in. Provide an offline deployment mode in which administrators pre-stage verified dependencies and model files.
- Avoid placing mutable downloaded resources inside the installed Skill directory. Use a dedicated, permission-restricted cache directory and reject symbolic links or unexpected file types.
- Run conversion in a sandbox with only the required input and output paths mounted. Deny access to unrelated user files, credentials, and environment variables.
- Restrict outbound network access during conversion after verified dependencies have been provisioned.
- Document whether the proprietary SDK performs telemetry, online license checks, or document uploads, and provide a supported network-disabled mode where possible.
- Pin
