Back to skill

Security audit

Upstage Ocr

Security checks for vulnerabilities and agentic risk

Overview

This OCR skill does what it says, but users should know their documents are sent to Upstage and results may be saved locally.

Install only if you are comfortable sending selected documents to Upstage for OCR. Avoid using it for highly confidential or regulated files unless third-party processing and async retention are acceptable, and prefer a private, random, owner-only output path instead of the documented default temp filename.

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
SKILL.md:191
Finding

Predictable Temporary File Path for Sensitive OCR Results

Content
View full analysis
/.ocr.json` (e.g., `/tmp/receipt.ocr.json`). Use `tempfile.gettempdir()` for cross-platform code. - **Override**: if the user specifies an output path, use it. - **Always print the resolved absolute path** in your response so the user can locate the file. ``` ### Technical Analysis The Skill directs implementations to construct an OCR output path in the shared system temporary directory using the input filename stem. `tempfile.gettempdir()` only identifies a temporary directory; it does not securely create a unique file. The resulting path is predictable. For example, processing `receipt.pdf` would produce `/tmp/receipt.ocr.json`. If an implementation follows this instruction and opens the destination normally, another local process may pre-create the filename or replace it with a symbolic link before the OCR result is written. OCR output can contain the complete text and coordinates extracted from confidential documents. Unless the implementation explicitly creates the output atomically with restrictive permissions, the file may also be exposed through overly permissive process defaults. The unsafe behavior is an instruction in the Skill rather than executable code included in the repository. Exploitation therefore depends on the consuming agent implementing the documented output behavior without additional secure-file protections. ### Attack Path 1. An attacker with access to the same host predicts the output filename from the source document name, such as `/tmp/receipt.ocr.json`. 2. Before OCR processing completes, the attacker creates that file or creates a symbolic link at that path. 3. The agent follows the Skill instructions and writes the OCR response to th ...[truncated 1208 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (9)

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

This code sends a local document file to an external OCR API over the network. While the behavior is expected for an OCR integration, it is still a real data-exfiltration boundary because file contents leave the local environment and the skill does not include safeguards such as user consent, sensitivity checks, or data-minimization guidance.

Content

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

md
import os
import requests

response = requests.post(
    "https://api.upstage.ai/v1/document-digitization",
    headers={"Authorization": f"Bearer {os.environ['UPSTAGE_API_KEY']}"},
    files={"document": open("scan.pdf", "rb")},

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly instructs uploading user-provided documents to a third-party OCR service, but it does not warn about privacy, consent, retention, or sensitivity of transmitted files. This is dangerous because users may unknowingly send confidential documents, and the async flow notes results are stored for 30 days, increasing exposure if sensitive data is processed.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
import requests

response = requests.post(
    "https://api.upstage.ai/v1/document-digitization",
    headers={"Authorization": f"Bearer {os.environ['UPSTAGE_API_KEY']}"},
    files={"document": open("scan.pdf", "rb")},
    data={"model": "ocr"}

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
import requests

response = requests.post(
    "https://api.upstage.ai/v1/document-digitization",
    headers={"Authorization": f"Bearer {os.environ['UPSTAGE_API_KEY']}"},
    files={"document": open("scan.pdf", "rb")},
    data={"model": "ocr"}

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
import requests

response = requests.post(
    "https://api.upstage.ai/v1/document-digitization",
    headers={"Authorization": f"Bearer {os.environ['UPSTAGE_API_KEY']}"},
    files={"document": open("scan.pdf", "rb")},
    data={"model": "ocr"}

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

The curl example instructs users to upload a document directly to a third-party OCR endpoint. This is risky in a skill because it operationalizes external transmission of potentially sensitive files without any embedded privacy notice or user-consent language.

Content

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

Sync — Basic OCR

bash
curl -X POST "https://api.upstage.ai/v1/document-digitization" \
  -H "Authorization: Bearer $UPSTAGE_API_KEY" \
  -F "document=@/path/to/image.jpg" \
  -F "model=ocr"

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

This example function uploads the specified file path to Upstage, creating the same external data transmission risk as the quick-start snippet. In agent contexts, such examples can normalize sending arbitrary user documents off-platform without any warning or confirmation step.

Content

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

md
def ocr_document(file_path):
    with open(file_path, "rb") as f:
        response = requests.post(
            "https://api.upstage.ai/v1/document-digitization",
            headers={"Authorization": f"Bearer {os.environ['UPSTAGE_API_KEY']}"},
            files={"document": f},

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

The async submission example uploads a potentially large document to a third-party service, and the surrounding text states results are stored for 30 days. That combination materially increases privacy risk because sensitive document contents are transmitted externally and retained longer than a transient request.

Content

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

bash
# 1. Submit
curl -X POST "https://api.upstage.ai/v1/document-digitization/async" \
  -H "Authorization: Bearer $UPSTAGE_API_KEY" \
  -F "document=@large.pdf" \
  -F "model=ocr"

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

This async Python example submits a document to Upstage and later downloads OCR results from external URLs, expanding the third-party data flow. In context, the skill makes off-platform document processing easy but does not require any consent, classification, or retention-aware handling for potentially sensitive files.

Content

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

md
import requests

api_key = os.environ["UPSTAGE_API_KEY"]
base = "https://api.upstage.ai/v1/document-digitization"

with open("large.pdf", "rb") as f:
    r = requests.post(

Static analysis

No suspicious patterns detected.