Back to skill

Security audit

PDF Converter

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed PDF/image conversion wrapper, but it depends on ComPDF downloads, a proprietary SDK, and local trial-usage tracking.

Before installing, decide whether you are comfortable running a proprietary PDF conversion SDK on your documents, allowing first-run downloads from ComPDF, and storing a trial usage counter locally. For sensitive PDFs, use an isolated environment, pre-provision the license and model files, and consider pinning or otherwise validating the SDK and model version.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T08 · Insecure Dependencies

Error
Location
SKILL.md:33
Finding

Unpinned Proprietary Python Dependency

Content
View full analysis
Remediation
View remediation
" ``` 2. Distribute a locked requirements file containing SHA-256 hashes and install it with: ```bash python -m pip install --require-hashes -r requirements.txt ``` 3. Obtain expected hashes from a separately authenticated source and verify each platform-specific wheel. 4. Review new SDK versions before updating the lock file. 5. Install the SDK in an isolated virtual environment with only the permissions required for conversion. 6. Where sensitive documents are processed, apply outbound network restrictions to the conversion process. 7. Document the exact supported SDK version rather than treating the latest locally installable wheel as authoritative. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/pdf-convert-compdf.py:316
Finding

Downloaded AI Model Is Loaded Without Integrity Verification

Content
View full analysis
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) ``` ```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_path.exists(): temp_path.unlink() download_file(DOCUMENT_AI_MODEL_URL, temp_path) if not temp_path.is_file() or temp_path.stat().st_size == 0: raise RuntimeError("Downloaded documentai.model is empty") temp_path.replace(model_path) break except Exception as exc: last_error = exc if temp_path.exists(): temp_path.unlink() if attempt >= len(DOCUMENT_AI_MODEL_RETRY_DELAYS): raise RuntimeError(f"Failed to prepare documentai.model: {exc}") from exc time.sleep(DOCUMENT_AI_MODEL_RETRY_DELA ...[truncated 3083 chars]
Remediation
View remediation
" def verify_sha256(path: Path, expected: str) -> None: digest = hashlib.sha256() with path.open("rb") as stream: for chunk in iter(lambda: stream.read(1024 * 1024), b""): digest.update(chunk) if digest.hexdigest() != expected: raise RuntimeError("documentai.model integrity verification failed") ``` 3. Perform verification immediately after download and delete the temporary file on mismatch. 4. Verify existing cached models before reuse rather than checking only their size. 5. Apply equivalent validation to paths supplied through `COMPDF_DOCUMENT_AI_MODEL`. 6. Pin the model to an explicit version and use a version-specific URL rather than a mutable generic path. 7. Make automatic model downloading opt-in, or clearly request user approval before the first download. 8. Run native model parsing in a sandbox with restricted filesystem and network access where sensitive documents are processed. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The manifest and description materially understate behavior: the skill performs remote downloads, local license enforcement, trial tracking, supports image input, and does not match the advertised XML capability. This mismatch can mislead operators into approving a skill they believe is local-only PDF conversion when it actually reaches out to third-party servers and changes local state.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 22)May include surrounding context.

md
- The entry point is `SKILL.md`; helper scripts are placed in `scripts/`.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill declares no explicit tool scope despite clearly requiring network, file read/write, and environment access. In agent environments, missing permission boundaries increases the chance the skill is invoked with broader capabilities than users expect, enabling silent downloads and filesystem changes.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Automatic downloads of license.xml and a large model file introduce supply-chain and privacy risks because execution depends on fetching remote content at runtime. Even if intended for product functionality, this expands trust to external infrastructure and can cause unexpected network egress and disk writes in supposedly local workflows.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The documentation acknowledges automatic downloads and file creation but does not present them as prominent privacy/system-impact warnings. In practice, users may run the skill expecting offline local conversion and unknowingly trigger network egress, large downloads, and persistent files, which is risky in restricted or sensitive environments.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script automatically downloads a license file and Document AI model from remote servers during normal conversion flow, even though the skill presents itself primarily as a local PDF conversion tool. This creates an unannounced network dependency and supply-chain trust boundary: a compromised server, redirected traffic, or unexpected remote content could alter tool behavior or introduce malicious artifacts the local process will then trust.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The tool performs automatic remote downloads without clear upfront disclosure in the CLI interface, so users invoking a local conversion command may unknowingly trigger network access and external file retrieval. This weakens informed consent and increases exposure to supply-chain, privacy, and policy-compliance risks, especially in restricted or offline environments.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill writes persistent usage-tracking data into the user's home directory for license enforcement, which exceeds the minimal scope expected for a one-shot file conversion utility. While not an immediate code-execution risk, it creates undisclosed statefulness, possible privacy concerns, and potential interference with multi-user or automated environments where hidden home-directory writes are undesirable.

Content

No source excerpt is available for this finding.

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

Scanner excerpt · License.txt (reported line 48)May include surrounding context.

text
------------------------------------------------------------------------

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.

IN NO EVENT SHALL PDF TECHNOLOGIES, INC. OR ITS AFFILIATES BE LIABLE FOR

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

These lines describe behavior beyond conversion itself: fingerprinting the license type, counting conversions, refusing service after a threshold, and directing users to a purchase URL. That licensing/marketing enforcement capability is not part of the manifest's stated purpose of converting PDFs for LLM processing.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/pdf-convert-compdf.py (reported line 294)May include surrounding context.

python
def resolve_converter(format_name: str):
    method_name = get_converter_method_name(format_name)
    converter = getattr(CPDFConversion, method_name, None)
    if converter is None:
        raise RuntimeError(f"Current SDK does not provide converter method: {method_name}")
    return converter