Back to skill

Security audit

onedrive-photo-batch

Security checks for vulnerabilities and agentic risk

Overview

This OneDrive photo indexing skill is purpose-aligned, but it deserves Review because it can bulk-send private photos and OCR text to third-party services, persist Microsoft auth tokens, and silently delete old recovery copies.

Review the config before installing. Use the default read-only mode unless you intentionally need delete, move, restore, or upload, and only grant Files.ReadWrite when necessary. Treat full indexing as bulk disclosure of selected photos to the configured OCR provider, and treat semantic search/embedding as disclosure of extracted text and queries. Use trusted HTTPS endpoints, protect API keys and the token cache, and be aware that local recovery copies older than 15 days may be removed automatically.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/onedrive_photo_batch.py:338
Finding

Private OneDrive Photos and API Credentials Can Be Sent to an Unrestricted OCR Endpoint

Content
View full analysis
str: if not self.endpoint or not self.api_key: raise RuntimeError("OCR endpoint/api_key 未配置") raw = image_path.read_bytes() b64 = base64.b64encode(raw).decode("utf-8") url = f"{self.endpoint}/chat/completions" payload = { "model": model, "messages": [ { "role": "user", "content": [ {"type": "text", "text": prompt or self.prompt}, {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{b64}"}}, ], } ], "max_tokens": self.max_tokens, "temperature": 0.1, } resp = requests.post( url, headers={"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"}, json=payload, timeout=self.timeout, ) ``` ### Technical Analysis The OCR client reads each downloaded OneDrive photo in full, Base64-encodes it, and places the encoded image in a JSON request sent to a configuration-controlled endpoint. Base64 is only a transport representation and provides no confidentiality. Sending photos to an OCR service is related to ...[truncated 1740 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/onedrive_photo_batch.py:384
Finding

OCR Text and Semantic Queries Can Be Sent to an Unrestricted Embedding Endpoint

Content
View full analysis
Optional[List[float]]: if not self.enabled: return None if not self.endpoint or not self.api_key or not self.model: raise RuntimeError("embedding 配置不完整") payload = {"model": self.model, "input": text} resp = requests.post( f"{self.endpoint}/embeddings", headers={"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"}, json=payload, timeout=self.timeout, ) if resp.status_code >= 400: raise RuntimeError(f"Embedding失败 {resp.status_code}: {resp.text[:500]}") data = resp.json() emb = data.get("data", [{}])[0].get("embedding") return emb ``` ### Technical Analysis When embedding is enabled, the client sends arbitrary input text to a configuration-controlled endpoint. During full indexing, this input is the OCR output extracted from a photo. During semantic search, it is the user's search query. The implementation does not require TLS, validate the endpoint hostname, constrain redirects, or redact sensitive content. It also transmits the embedding API key to the selected destination. Embedding is an optional declared feature, so network transmission is functionally relevant. Nevertheless, accepting an unrestricted destination exc ...[truncated 1306 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/onedrive_photo_batch.py:175
Finding

MSAL Token Cache Is Persisted Without Enforced Owner-Only Permissions

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (16)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill states that every run silently performs 15-day cleanup of the local recycle area, deleting recovery copies without an explicit runtime warning or user confirmation. In a photo-management context, this weakens the safety net for mistaken deletions and can lead to irreversible loss of locally retained recovery data.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill invokes a Python script that can read and write local files, access network resources, and perform destructive remote operations, but the manifest does not declare any explicit tool scope or permission boundaries. This makes the operational trust boundary opaque and increases the chance of unintended execution with broader capabilities than the user expects.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The description and trigger conditions are broad enough to activate on common requests about OneDrive photos, indexing, deletion, recovery, and cleanup, including destructive workflows. Overbroad activation can cause the agent to select this skill in situations where the user did not clearly intend bulk cloud or local file operations.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest says the skill supports moving, uploading, deleting, restoring, and recycle-bin governance, but this example configuration declares only the Microsoft Graph scope Files.Read. That creates a semantic mismatch between the advertised operational scope and the permissions implied by the shipped configuration.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

This configuration sends OneDrive photo content to a third-party OCR API endpoint, which creates a real data exfiltration path for potentially sensitive images and extracted text. In the context of a photo batch-processing skill, the risk is heightened because uploads may occur at scale and may include personal documents, faces, locations, or other private content.

Content

Scanner excerpt · references/config.example.json (reported line 15)May include surrounding context.

json
"log_file": "/root/.openclaw/workspace/tmp/onedrive_photo_batch/skill.log"
  },
  "ocr": {
    "endpoint": "https://api.siliconflow.cn/v1",
    "api_key": "YOUR_SILICONFLOW_API_KEY",
    "default_model": "Qwen/Qwen3-VL-8B-Instruct",
    "prompt": "请进行OCR,逐行输出可见文字,再给三条关键内容摘要。",

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Line L18 hard-codes the instruction "请进行OCR,逐行输出可见文字,再给三条关键内容摘要。", which directs the model to produce output in Chinese. This is a natural-language locale constraint with no visible opt-in, user choice, or justification in the file, so it may violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

The embedding configuration transmits image-derived text or metadata to a third-party embedding API, creating another external disclosure channel. While embeddings may seem lower sensitivity than raw images, they can still leak semantic information about private photos, documents, albums, or indexed content, especially when processed in bulk.

Content

Scanner excerpt · references/config.example.json (reported line 39)May include surrounding context.

json
},
  "embedding": {
    "enabled": true,
    "endpoint": "https://api.siliconflow.cn/v1",
    "api_key": "YOUR_SILICONFLOW_API_KEY",
    "model": "BAAI/bge-m3",
    "timeout_sec": 60

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

The default configuration pre-populates a third-party OCR endpoint, making external transmission part of the expected workflow once an API key is added. In a bulk photo-processing skill, secure-by-default behavior matters; pointing at an external provider by default increases the chance of unreviewed data export.

Content

Scanner excerpt · scripts/onedrive_photo_batch.py (reported line 97)May include surrounding context.

python
"log_file": str(root / "tmp/onedrive_photo_batch/skill.log"),
        },
        "ocr": {
            "endpoint": "https://api.siliconflow.cn/v1",
            "api_key": "",
            "default_model": "Qwen/Qwen3-VL-8B-Instruct",
            "prompt": "请进行OCR,逐行输出可见文字,再给三条关键内容摘要。",

External Transmission

Medium
Category
Data Exfiltration
Confidence
83% confidence
Finding

The default embedding configuration references an external service endpoint, normalizing outbound transfer of OCR-derived text to a third party. Although embedding is disabled by default, the bundled endpoint still encourages a privacy-sensitive architecture without strong consent and governance controls.

Content

Scanner excerpt · scripts/onedrive_photo_batch.py (reported line 110)May include surrounding context.

python
},
        "embedding": {
            "enabled": False,
            "endpoint": "https://api.siliconflow.cn/v1",
            "api_key": "",
            "model": "BAAI/bge-m3",
            "timeout_sec": 60,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This function base64-encodes full photo contents and sends them to an external OCR service, but there is no explicit runtime consent gate, warning, or per-operation acknowledgement at the call site. Because the skill processes OneDrive photos in bulk, this can exfiltrate sensitive personal images, documents, and metadata to a third-party provider without sufficiently explicit user awareness.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This call transmits raw image data to an external OCR endpoint over the network. In the context of a photo-batch skill operating on personal OneDrive content, that transfer is materially sensitive because it can include private photos and embedded text from documents at scale.

Content

Scanner excerpt · scripts/onedrive_photo_batch.py (reported line 365)May include surrounding context.

python
"max_tokens": self.max_tokens,
            "temperature": 0.1,
        }
        resp = requests.post(
            url,
            headers={"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"},
            json=payload,

Tainted flow: 'url' from requests.post (line 274, network input) → requests.post (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/onedrive_photo_batch.py (reported line 365)May include surrounding context.

python
"max_tokens": self.max_tokens,
            "temperature": 0.1,
        }
        resp = requests.post(
            url,
            headers={"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"},
            json=payload,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The code sends OCR-derived text to an external embedding API without an explicit disclosure or consent checkpoint. OCR text can contain highly sensitive information from photos such as IDs, addresses, financial records, or private notes, so forwarding it to another external service expands data exposure beyond the original OCR step.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

This call sends extracted OCR text to an external embedding service, creating an additional outbound data flow of potentially sensitive content. Since the skill is designed for indexing and semantic search, the volume and persistence of transmitted content can increase privacy and compliance risk.

Content

Scanner excerpt · scripts/onedrive_photo_batch.py (reported line 395)May include surrounding context.

python
if not self.endpoint or not self.api_key or not self.model:
            raise RuntimeError("embedding 配置不完整")
        payload = {"model": self.model, "input": text}
        resp = requests.post(
            f"{self.endpoint}/embeddings",
            headers={"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"},
            json=payload,

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest description and operational instructions are presented in Chinese, and the file does not indicate that users may choose another language or that the locale restriction is intentional and justified. This can constitute a language policy issue if users are not expected to operate in Chinese by default.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The natural-language documentation and default OCR prompt are written exclusively in Chinese, including user-visible runtime messages elsewhere in the file, with no indication that users may choose another language. Under the policy criteria, forcing a specific language without opt-in can be a locale-policy issue unless clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.