Back to skill

Security audit

Mistral OCR

Security checks for vulnerabilities and agentic risk

Overview

The skill is a disclosed cloud OCR tool, but its open-ended dependency on the Mistral SDK creates a real supply-chain review risk.

Install only after pinning mistralai to a reviewed non-affected version, avoid processing confidential files unless Mistral upload is acceptable, prefer a secret manager or temporary environment variable for the API key, and avoid opening generated HTML from untrusted documents.

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 (3)

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unbounded Third-Party Dependency Allows Unreviewed Package Releases

Content
View full analysis
=0.0.9 ``` The dependency is installed through the documented command in `SKILL.md`: ```bash pip install -r requirements.txt ``` ### Technical Analysis The lower-bound-only version constraint permits `pip` to install any current or future release of the `mistralai` package newer than version `0.0.9`. No upper bound, exact version, or cryptographic package hash is provided. Consequently, the code that actually runs can change after this Skill has been reviewed. A compromised upstream account, malicious future release, or supply-chain compromise could introduce arbitrary installation-time or import-time behavior into the Skill's environment. ### Attack Path 1. An attacker compromises the upstream package, its publishing credentials, or a future eligible release. 2. The attacker publishes a malicious `mistralai` version satisfying `>=0.0.9`. 3. A user follows the documented installation procedure. 4. `pip` resolves and installs the malicious release because no exact version or hash is enforced. 5. Malicious package code executes during installation, import, or API-client initialization. 6. The package may access the process environment, including `MISTRAL_API_KEY`, input documents, and files available to the invoking user. ### Impact Assessment Successful exploitation would execute code with the privileges of the user installing or running the Skill. Within those privileges, a malicious dependency could steal the Mistral API key, inspect or alter OCR documents, modify output, access user-readable local files, or perform network operations. This finding does not establish that the currently published `mistralai` package is malicious. The risk arises because future or compromised releases are automatically eligible for installation. ]] ...[truncated 1 chars]
Remediation
View remediation
``` - Generate a lock file containing exact versions for all transitive dependencies. - Require cryptographic hashes during installation, for example with `pip install --require-hashes`. - Use a controlled package index or trusted internal mirror where appropriate. - Integrate dependency vulnerability and provenance scanning into release workflows. - Review and deliberately approve dependency upgrades instead of accepting future releases automatically. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mistral_ocr.py:151
Finding

Untrusted OCR Output Is Embedded into HTML Without Sanitization

Content
View full analysis

Page {i+1}

{page_md}") html_content = f""" {input_path.stem} {"".join(all_html)} """ output_path = output_dir / "result.html" with open(output_path, 'w', encoding='utf-8') as f: f.write(html_content) ``` The preprocessing function also converts encoded markup into active delimiters: ```python def replace_html_entities(text): """Replace HTML entities with regular characters (for Typora compatibility).""" replacements = { ">": ">", "<": "<", "&": "&", """: '"', "'": "'", " ": " ", } for old, new in replacements.items(): text = text.replace(old, new) return text ``` ### Technical Analysis OCR-derived Markdown is untrusted content because it originates from a user-selected or potentially attacker-supplied document and is generated by an external OCR service. The HTML output branch inserts this content directly into an HTML document without escaping or sanitization. The `replace_html_entities()` function increases the exposure by converting `<` and `>` into literal angle brackets before insertion. Text that was previously encoded can therefore become active HTML markup. The implementation also does not use a safe Markdown-to-HTML renderer or a restrictive HTML allowlist. ### Attack Path 1. An attacker creates a PDF or image containing text designed to be recognized as HTML, such as script-c ...[truncated 1191 chars]
Remediation
View remediation
` element. - Consider adding a restrictive Content Security Policy to generated documents as defense in depth. - Add regression tests using encoded tags, script elements, event handlers, `javascript:` URLs, SVG payloads, and external image references. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
README.md:65
Finding

Documentation Encourages Persistent Plaintext Storage of the API Key

Content
View full analysis
> ~/.zshrc source ~/.zshrc ``` Similar permanent shell-configuration guidance is printed by `scripts/mistral_ocr.py` when the key is missing. ### Technical Analysis The recommended command stores a long-lived API credential as plaintext in a shell startup file. Shell configuration files may be copied into backups, included accidentally in support archives, read by other processes running as the same user, exposed through overly permissive filesystem permissions, or inadvertently committed to a repository. Although environment-variable use avoids hardcoding the key in the Skill source, persisting the secret directly in `.zshrc` or `.bashrc` does not provide secret-at-rest protection or lifecycle management. ### Attack Path 1. A user follows the permanent setup instructions and writes the API key into a shell startup file. 2. The file or one of its backups becomes accessible through weak permissions, local malware, repository publication, workstation backup exposure, or accidental sharing. 3. An attacker extracts the plaintext `MISTRAL_API_KEY`. 4. The attacker uses the key to authenticate to Mistral services until the key is revoked or expires. ### Impact Assessment An exposed key could permit unauthorized API use within the key's assigned Mistral account scope. Potential consequences include usage charges, quota depletion, service abuse, and access to any API capabilities granted to that credential. This issue does not grant operating-system privilege escalation by itself. Its scope is limited by the Mistral permissions, quotas, and account controls associated with the stolen key. ]]>
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (8)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/mistral_ocr.py (reported line 24)May include surrounding context.

python
def get_api_key():
    """Get API Key from environment variable."""
    api_key = os.environ.get("MISTRAL_API_KEY")
    if not api_key:
        print("""

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 72)May include surrounding context.

Temporary (current terminal session)

export MISTRAL_API_KEY=your_api_key_here

Permanent (add to ~/.zshrc or ~/.bashrc)

echo 'export MISTRAL_API_KEY=your_api_key_here' >> ~/.zshrc source ~/.zshrc

text

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill advertises behavior that requires access to environment variables, reading local files, and writing output files, but it does not explicitly declare any tool scope such as permissions or allowed-tools. This creates a transparency and least-privilege problem: a user or runtime may not have clear visibility into what capabilities the skill expects, increasing the risk of overbroad access or unintended handling of local documents and API secrets.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/mistral_ocr.py (reported line 33)May include surrounding context.

python
To use this tool, you need a Mistral API key:

1. Visit: https://console.mistral.ai/home
2. Sign up/Login and create an API key
3. Set the environment variable:
   
   export MISTRAL_API_KEY=your_api_key

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script transmits the full input document to Mistral's remote OCR service, but it does not give an explicit runtime warning or require affirmative acknowledgment that document contents are leaving the local system. In a skill context, users may assume local OCR processing, so sensitive PDFs or images could be unintentionally disclosed to a third-party service.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency is specified as mistralai>=0.0.9, which allows installation of any newer release, including versions that may introduce breaking changes or malicious code. In a supply-chain context, unpinned dependencies weaken reproducibility and make it easier for compromised upstream releases to be pulled into deployments without review.

Content

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

text
mistralai>=0.0.9

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
95% confidence
Finding

The manifest references mistralai without pinning, while advisories exist indicating some PyPI releases were malicious. Because the allowed version range is open-ended, an install could resolve to an affected or trojanized release, creating a direct software supply-chain compromise risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The code retrieves an API key from the environment and uses it to authenticate with an external service. While this is functionally necessary, there is no explicit disclosure in the script that a credential from the environment will be consumed for remote requests, which fits the missing-warning criterion for sensitive environment variable access in code files.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.