Back to skill

Security audit

Multimodal Image Understanding

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent BYOK image-analysis helper, but it needs Review because it can fetch arbitrary URLs from the user's machine and send images, prompts, and API keys to configurable endpoints without strong transport or SSRF safeguards.

Install only if you understand that selected images, image URLs, prompts, optional system prompts, and API credentials are sent to the configured provider. Use HTTPS endpoints you control or trust, prefer environment variables for keys, avoid sensitive images unless the provider is approved, and avoid using arbitrary/private-network image URLs until URL validation and download limits are added.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/multimodal_understand.py:105
Finding

Arbitrary Image URL Fetching Enables Server-Side Request Forgery and Data Exfiltration

Content
View full analysis
tuple[bytes, str | None]: """Download URL content and return (bytes, content_type_from_header).""" req = urllib.request.Request(url, headers={"User-Agent": "multimodal-image-understanding/1.0"}) ctx = ssl.create_default_context() with urllib.request.urlopen(req, timeout=timeout, context=ctx) as resp: if resp.status != 200: raise SystemExit(f"Error: image download failed, HTTP {resp.status}") ct = resp.headers.get("Content-Type", "").split(";")[0].strip().lower() or None return resp.read(), ct ``` ```python if _is_url(image): if image_mode == "base64": data, content_type = _download_url(image, timeout=timeout) mime = _guess_mime_from_url(image, content_type) b64 = base64.standard_b64encode(data).decode("ascii") return {"source": "base64", "mime": mime, "data": b64, "url": None} ``` ### Technical Analysis The `--image` argument accepts arbitrary HTTP or HTTPS URLs. When `image_mode` is set to `base64`, the application retrieves the supplied URL through `urllib.request.urlopen()` without applying destination restrictions. The implementation does not: - Reject loopback, private, link-local, multicast, reserved, or cloud metadata IP ranges. - Resolve and validate hostnames before connecting. - Revalidate the destination after DNS resolution. - Disable redirects or validate each redirect target. - Verify that the response body is a genuine supported image. - Apply a maximum response size to remote downloads. Python's URL handling follows HTTP redirects by default. Consequently, an initially public URL may redirect to an internal address. The respon ...[truncated 1906 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/multimodal_understand.py:183
Finding

Unrestricted Plaintext API Endpoints Can Expose Credentials, Prompts, and Image Data

Content
View full analysis
dict: payload = json.dumps(body).encode("utf-8") req = urllib.request.Request(url, data=payload, method="POST", headers=headers) ctx = ssl.create_default_context() try: with urllib.request.urlopen(req, timeout=timeout, context=ctx) as resp: ``` Authentication credentials are added directly to outbound headers: ```python def _anthropic_headers(cfg: dict) -> dict: headers = { "content-type": "application/json", "anthropic-version": "2023-06-01", } if cfg.get("api_key"): if cfg.get("auth_header"): headers[cfg["auth_header"]] = cfg["api_key"] else: headers["x-api-key"] = cfg["api_key"] return {k: v for k, v in headers.items() if v} ``` ```python def _openai_headers(cfg: dict) -> dict: headers = {"content-type": "application/json"} if cfg.get("api_key"): if cfg.get("auth_header"): headers[cfg["auth_header"]] = cfg["api_key"] else: headers["Authorization"] = f"Bearer {cfg['api_key']}" return {k: v for k, v in headers.items() if v} ``` Endpoint validation only checks that a value exists: ```python if not cfg.get("endpoint"): raise SystemExit("Error: config.endpoint is required") if not cfg.get("model"): raise SystemExit("Error: config.model is required") ``` ### Technical Analysis The endpoint is entirely configuration-controlled and is not restricted to HTTPS. The same request carries: - The provider API key. - The user prompt. - A local image encoded as Base64, or a reference to a remote image. - An optional configured sys ...[truncated 2567 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (13)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill clearly instructs reading local configuration files, expanding environment variables, and sending data to external APIs, but it declares no explicit tool or permission scope. That creates an authorization and transparency gap: an agent may access files, env vars, and network without users being clearly informed of those capabilities. In this context, the omission is more dangerous because the skill handles API keys and user-supplied images, both of which are sensitive inputs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill description and workflow do not prominently warn that the image content and the user's prompt will be transmitted to third-party multimodal providers. This is a real privacy and data-handling issue because users may submit sensitive images or OCR targets without understanding that the data leaves the local environment. The risk is elevated by the skill's purpose: its core function is external processing of potentially private visual data.

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 · SKILL.md (reported line 25)May include surrounding context.

bash
# 1. 创建配置文件(一次性)
mkdir -p ~/.config/multimodal-image-understanding
cp assets/config.example.json ~/.config/multimodal-image-understanding/config.json
# 编辑 config.json:填入 api_key、model、endpoint

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 44)May include surrounding context.

json
{
  "protocol": "openai",
  "endpoint": "https://api.openai.com/v1",
  "model": "gpt-4o",
  "api_key": "sk-...",
  "max_tokens": 1024,

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 · references/config-schema.md (reported line 74)May include surrounding context.

json
{
  "protocol": "openai",
  "endpoint": "https://api.openai.com/v1",
  "model": "gpt-4o",
  "api_key": "sk-...",
  "max_tokens": 1024,

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
## 安全建议

- 配置文件中的 API key 直接存储在磁盘,请设置文件权限 `chmod 600`。
- 推荐在配置文件中使用 `${ENV_VAR}` 引用环境变量,避免密钥落盘。
- 不要将配置内容回显给用户。

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 · assets/config.example.json (reported line 3)May include surrounding context.

json
{
  "protocol": "anthropic",
  "endpoint": "https://api.minimaxi.com/anthropic",
  "model": "MiniMax-M3",
  "api_key": "${ANTHROPIC_AUTH_TOKEN}",
  "max_tokens": 1024,

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 · references/config-schema.md (reported line 60)May include surrounding context.

md
{
  "protocol": "anthropic",
  "endpoint": "https://api.minimaxi.com/anthropic",
  "model": "MiniMax-M3",
  "api_key": "${ANTHROPIC_AUTH_TOKEN}",
  "max_tokens": 1024,

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 · references/config-schema.md (reported line 101)May include surrounding context.

md
{
  "protocol": "anthropic",
  "endpoint": "https://api.minimaxi.com/anthropic",
  "model": "MiniMax-M3",
  "api_key": "${ANTHROPIC_AUTH_TOKEN}",
  "max_tokens": 1024,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script sends the user-provided prompt and image to a third-party upstream model endpoint, but the CLI flow does not present a clear consent/privacy warning at the point of transmission. In this skill’s context, the entire purpose is remote multimodal analysis, so the data transfer is expected, but it still creates a real privacy and data-disclosure risk if users supply sensitive local images or confidential text without realizing they will leave the local environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The entire skill documentation is presented in Chinese, which can amount to a language policy constraint if users are not offered a language or locale choice. The file does not indicate that the Chinese-only presentation is intentional for a specific locale or provide an alternative language option.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The document explicitly recommends converting images to base64 and uploading them to upstream APIs, but it does not warn that this transfers potentially sensitive image content off-device to third-party services. In a multimodal image-analysis skill, users may submit screenshots, IDs, documents, or other private images, so omission of a privacy/data-transfer warning can lead to unintentional disclosure.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

Natural-language descriptions, help text, and runtime messages in this file are consistently Chinese-only. Under the stated policy, a skill should not impose a language or locale without opt-in unless the locale restriction is explicit and justified.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.