Back to skill

Security audit

Ollama OCR

Security checks for vulnerabilities and agentic risk

Overview

This OCR skill is purpose-aligned and disclosed, but users should understand that images are sent to a configured Ollama HTTP endpoint rather than processed entirely inside the skill process.

Install only if you trust the Ollama service at 172.17.0.2:11434 in your environment. Do not use it for highly sensitive images unless you have verified that endpoint is your intended local Ollama instance and that the Docker/network path is trusted.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
ollama_ocr.py:8
Finding

Image Data Transmitted over Plaintext HTTP to a Hard-Coded Network Endpoint

Content
View full analysis

Vulnerability Details

File Location: ollama_ocr.py, lines 8–38
Vulnerability Type: Plaintext transmission of potentially sensitive image data to a hard-coded network address
Risk Level: Medium

Vulnerable Code:

python
OLLAMA_HOST = "172.17.0.2"
OLLAMA_PORT = "11434"
DEFAULT_MODEL = "glm-ocr:latest"

def ollama_ocr(image_path, model=DEFAULT_MODEL):
    """Call Ollama API for image text recognition"""
    
    try:
        # Read and encode image
        with open(image_path, 'rb') as f:
            img_b64 = base64.b64encode(f.read()).decode()
        
        # Prepare request
        data = json.dumps({
            'model': model,
            'messages': [{
                'role': 'user',
                'content': 'Extract all text from this image',
                'images': [img_b64]
            }]
        }).encode()
        
        url = f"http://{OLLAMA_HOST}:{OLLAMA_PORT}/api/chat"
        req = urllib.request.Request(
            url,
            data=data,
            headers={'Content-Type': 'application/json'}
        )
        
        # Get response
        resp = urllib.request.urlopen(req, timeout=120)

Technical Analysis

The function reads the complete contents of a user-selected image, Base64-encodes them, and transmits them to the fixed address 172.17.0.2:11434 using unencrypted HTTP. Base64 only changes the data representation and does not provide confidentiality.

The address is intended to represent an Ollama service reachable through a Docker network. However, private IP ownership is environment-dependent and can change when containers or networks are recreated. If an untrusted container or service obtains this address, it can receive the entire image. An attacker with visibility into the relevant host or container network could also observe the plaintext request.

No authentication or server identity verification is performe ...[truncated 1485 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace the hard-coded destination with an explicit, validated configuration value, such as an environment variable or protected configuration file.
  2. Default to a loopback endpoint such as 127.0.0.1 when Ollama runs in the same security boundary. Consider a Unix-domain socket where supported.
  3. Use HTTPS with certificate validation when image data must cross a network boundary. Do not disable TLS certificate or hostname verification.
  4. Authenticate the Ollama endpoint or place it behind an authenticated local proxy so that the client can verify the intended recipient.
  5. Apply an allowlist for acceptable schemes, hosts, and ports. Reject plaintext remote endpoints unless the user explicitly enables them after receiving a security warning.
  6. Inform users that the complete image is transmitted to the configured service and obtain explicit confirmation before processing sensitive images through a non-loopback endpoint.
  7. Pin or otherwise control the Docker service identity instead of relying solely on a potentially reassigned container IP address.
  8. Update SKILL.md to clarify that “offline” does not inherently mean that image data remains within the current process and that plaintext container-network transmission may still be observable.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill documentation explicitly directs users to a network endpoint (http://172.17.0.2:11434) and references a Python implementation with configurable OLLAMA_HOST, but it declares no permissions or allowed-tools scope. That creates a mismatch between declared and actual capabilities, which can lead to unintended network access without transparent policy gating or user review. In this context the network use appears functional rather than malicious, but undeclared connectivity is still a real security issue because it weakens least-privilege controls and could be repurposed for unexpected internal service access.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill description promises local offline OCR, but the implementation base64-encodes the image and sends it over HTTP to another host at 172.17.0.2:11434. This creates a confidentiality and trust-boundary issue because potentially sensitive image contents leave the calling process without clear disclosure, and the transmission is not local in-process execution as implied.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The tool transmits raw image contents, encoded as base64, over plain HTTP with no warning to the user. If the image contains sensitive information, it may be exposed to interception on the local network path or to an unintended service endpoint, especially since the destination is a separate host rather than an in-process OCR library.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The code hard-codes a non-loopback host and port, which silently expands the trust boundary beyond a purely local file-processing tool. While this is not inherently malicious, it can cause data to be sent to an unexpected container or network peer, increasing the chance of accidental data exposure or misuse in environments where 172.17.0.2 is not fully trusted.

Content

No source excerpt is available for this finding.