Back to skill

Security audit

Mistral PDF OCR

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Mistral OCR helper, but a malformed OCR response could cause it to write files outside the chosen output folder.

Review before installing. Use it only for documents you are allowed to send to Mistral, store outputs in a controlled directory, and prefer fixing the output filename containment issue and pinning mistralai to a vetted version before use.

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

Error
Location
scripts/mistral_ocr_extract.py:253
Finding

Untrusted OCR identifiers allow arbitrary file overwrite through path traversal

Content
View full analysis
Remediation
View remediation
Path: if not remote_name or Path(remote_name).is_absolute(): raise CLIError("Unsafe output filename") normalized_name = Path(remote_name).name if normalized_name != remote_name or normalized_name in {".", ".."}: raise CLIError("Unsafe output filename") if not re.fullmatch(r"[A-Za-z0-9._-]+", normalized_name): raise CLIError("Unsafe output filename") resolved_parent = parent.resolve() destination = (resolved_parent / normalized_name).resolve() try: destination.relative_to(resolved_parent) except ValueError as exc: raise CLIError("Output path escapes its destination directory") from exc return destination ``` Use the validated result for both image and table output paths. For tables, validate the identifier before appending the trusted extension. ]]>

T08 · Insecure Dependencies

Note
Location
scripts/requirements.txt:1
Finding

Unbounded dependency version prevents reproducible and reviewed installations

Content
View full analysis
=1.0.0 ``` ### Technical Analysis The dependency manifest specifies only a minimum version and has no upper bound, lockfile, or package hashes. Every future release satisfying `>=1.0.0` is therefore eligible for installation without being part of the reviewed project state. This does not demonstrate that the current `mistralai` package is malicious. However, it creates a non-reproducible supply-chain boundary: future package releases may introduce compromised code, unexpected behavior, or incompatible API changes without any modification to this repository. The imported SDK executes Python code in the context of the OCR process and receives the Mistral API key during client construction. A compromised dependency would therefore execute with the permissions and environment of the invoking user. ### Attack Path 1. A future eligible `mistralai` release is compromised or otherwise contains unsafe code. 2. A user installs dependencies using the provided requirements file. 3. The package manager selects that release because the manifest permits every version at or above `1.0.0`. 4. The script imports `mistralai` and constructs a `Mistral` client. 5. Dependency code executes with the current user's privileges and can potentially access local files, network resources, process environment variables, and `MISTRAL_API_KEY`. ### Impact Assessment The exact impact depends on the behavior of a compromised future dependency. Because Python dependencies execute in-process, the theoretical scope includes: - Reading or exfiltrating `MISTRAL_API_KEY`. - Accessing files available to the current user. - Modifying OCR inputs or generated outputs. - Making unauthorized network requests. - Executing arbitrary Python behavior with the invoking user's privileges. No direct pr ...[truncated 87 chars]
Remediation
View remediation
``` A hash-locked requirements file should then record the expected distribution hashes for the SDK and all transitive dependencies. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (9)

Lp1

High
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The script reads MISTRAL_API_KEY from the environment, which is a sensitive capability, yet the finding indicates this capability is not declared in the skill's permissions. In an agent setting, undeclared secret access weakens least-privilege guarantees and can cause users or orchestrators to invoke the skill without understanding it consumes confidential credentials.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

This reference identifies an external OCR endpoint, which means document contents may leave the local environment and be processed by a third party. In a skill specifically designed for OCR via Mistral, this is expected behavior, but it still constitutes a real data-exposure risk if users are not clearly informed before sensitive files are sent.

Content

Scanner excerpt · references/mistral_ocr_api.md (reported line 7)May include surrounding context.

md
## Endpoints

- **OCR**: `POST https://api.mistral.ai/v1/ocr`
- **Files upload**: `POST https://api.mistral.ai/v1/files` with `purpose="ocr"`

## Default model

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

The files upload endpoint enables sending complete PDFs to Mistral's infrastructure for OCR processing. Although this is core to the skill's intended function, it creates a genuine external-transmission risk because full source documents may contain highly sensitive information and the reference provides no warning or safeguard language.

Content

Scanner excerpt · references/mistral_ocr_api.md (reported line 8)May include surrounding context.

md
## Endpoints

- **OCR**: `POST https://api.mistral.ai/v1/ocr`
- **Files upload**: `POST https://api.mistral.ai/v1/files` with `purpose="ocr"`

## Default model

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill explicitly instructs users to upload local PDFs or provide public document/image URLs to a third-party OCR service, but it does not warn that full document contents will be transmitted off-system. In an OCR/document-processing context, files often contain sensitive personal, financial, legal, or proprietary data, so omission of a disclosure/consent step creates a real privacy and data-handling risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documentation explicitly states that full OCR outputs, extracted images, tables, and the raw API response are written to disk. Because OCR inputs commonly contain sensitive documents, this creates a real privacy and data-retention risk if users or integrators are not clearly warned that potentially confidential content will be persisted unencrypted and possibly left behind after processing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

When given a local file, the script uploads the document contents to Mistral's remote Files API for OCR. Because this skill handles PDFs and images that may contain sensitive business or personal information, failing to provide an explicit user-facing notice/consent mechanism creates a real data exfiltration and privacy risk, especially in an agent workflow where upload may be implicit.

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/mistral_ocr_extract.py (reported line 61)May include surrounding context.

python
return [_to_plain_dict(v) for v in obj]
    # Dataclasses
    if hasattr(obj, "__dataclass_fields__"):
        return {k: _to_plain_dict(getattr(obj, k)) for k in obj.__dataclass_fields__.keys()}
    # Plain objects: best effort
    if hasattr(obj, "__dict__") and not isinstance(obj, (str, int, float, bool)):
        return {k: _to_plain_dict(v) for k, v in vars(obj).items() if not k.startswith("_")}

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency is specified as mistralai>=1.0.0, which allows installation of any future release rather than a known-good version. In a security-sensitive context, this creates supply-chain risk because builds are not reproducible and could silently pull a compromised or breaking release, including versions later found to be malicious.

Content

Scanner excerpt · scripts/requirements.txt (reported line 1)May include surrounding context.

text
mistralai>=1.0.0

Unverifiable Dependency: mistralai has 2 known advisory(ies) (GHSA-wx9m-wx4f-4cmg (Malicious dropper in mistralai 2.4.6 PyPI package); MAL-2026-3608 (Malicious code in mistralai (PyPI))), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The manifest references mistralai without pinning, while advisories exist for malicious releases of that package. Because the allowed range can resolve to affected versions, the project may install a malicious package at build or deploy time, leading to arbitrary code execution, credential theft, or compromise of document data processed by the OCR skill.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.