Back to skill

Security audit

Image Recognize

Security checks for vulnerabilities and agentic risk

Overview

This image-recognition skill has a coherent Baidu-based purpose, but it can upload arbitrary local file contents or fetched URLs to Baidu without enough scoping or consent controls.

Install only if you are comfortable with selected images being processed by Baidu. Do not use it on private, regulated, biometric, credential-bearing, or proprietary images, and avoid giving it arbitrary local paths or internal/private-network URLs until path, URL, file-type, size, and consent controls 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 (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/image_recognize.py:88
Finding

Unrestricted Local File and URL Ingestion Enables Sensitive Data Disclosure and SSRF

Content
View full analysis

Vulnerability Details

File Location: scripts/image_recognize.py, lines 88–131
Vulnerability Type: Unrestricted file access, server-side request forgery, and external data disclosure
Risk Level: High

Vulnerable Code

python
# Handle network URLs
if value.startswith(("http://", "https://")):
    try:
        response = requests.get(value, timeout=30)
        response.raise_for_status()
        return base64.b64encode(response.content).decode()
    except requests.RequestException as e:
        raise Exception(f"Failed to download network image: {e}")

# Handle local file paths
if os.path.exists(value):
    with open(value, "rb") as f:
        return base64.b64encode(f.read()).decode()
else:
    raise FileNotFoundError(f"Image file does not exist: {value}")


def recognize_image(image_b64: str, api_key: str) -> dict:
    """
    Call the image-recognition API.
    Args:
        image_b64: Base64-encoded image
        api_key: Baidu API key
    Returns:
        API response
    """
    api_url = QIANFAN_BASE_URL + "/v2/tools/image_general"
    api_url, headers = resolve_sandbox_url(api_url, api_key)

    payload = {
        "image_b64": image_b64
    }

    try:
        response = requests.post(api_url, json=payload, headers=headers, timeout=30)
        response.raise_for_status()

Technical Analysis

The --image argument is treated as either an unrestricted HTTP(S) URL or an arbitrary local file path. The code does not:

  • Restrict local access to an approved image or workspace directory.
  • Resolve and validate paths against traversal or symbolic-link escapes.
  • Verify that the input is a supported image by decoding its contents.
  • Enforce the documented 4 MB size limit.
  • Restrict URL destinations by hostname or resolved IP address.
  • Block loopback, private, link-local, reserved, or cloud metadata addresses.
  • Validate redirect destinatio ...[truncated 2533 chars]
Remediation
View remediation

Remediation Suggestions

  1. Constrain local file access

    • Accept only files located within an explicitly approved upload or workspace directory.
    • Canonicalize both the approved root and requested path with Path.resolve().
    • Reject paths outside the approved root and prevent symbolic-link escapes.
    • Prefer file handles supplied by a trusted platform upload mechanism over arbitrary path strings.
  2. Validate actual image contents

    • Decode the input with a maintained image library and allow only required formats.
    • Do not rely solely on filename extensions or response Content-Type.
    • Reject malformed files, unsupported formats, and content that cannot be decoded as an image.
    • Re-encode the decoded image before transmission to ensure unrelated embedded input is not forwarded unchanged.
  3. Enforce resource limits

    • Enforce the documented 4 MB maximum before Base64 conversion.
    • Stream URL responses with a strict byte limit instead of loading unlimited response bodies into memory.
    • Limit decoded dimensions and pixel counts to prevent decompression-bomb denial of service.
  4. Prevent SSRF

    • Resolve the destination hostname and reject loopback, private, link-local, multicast, reserved, and unspecified IP ranges.
    • Allow only HTTP(S), preferably HTTPS.
    • Disable redirects or validate every redirect destination using the same hostname and IP rules.
    • Consider an explicit domain allowlist when remote image sources can be constrained.
    • Apply network-level egress controls so the Skill cannot reach metadata, loopback, or private-network services.
  5. Improve consent and disclosure

    • Clearly disclose in SKILL.md that selected image content is uploaded to Baidu.
    • Require explicit user confirmation before transmitting local files when the platform has not already obtained informed upload consent.
    • Avoid logging Base64 image content, API credent ...[truncated 280 chars]
Vulnerability Patterns
  • 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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (10)

Tainted flow: 'headers' from os.environ.get (line 300, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/image_recognize.py (reported line 130)May include surrounding context.

python
}

    try:
        response = requests.post(api_url, json=payload, headers=headers, timeout=30)
        response.raise_for_status()
        result = response.json()

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill is described as generic image recognition, but the documented output includes similar-image retrieval and external reference links, which extends behavior beyond simple classification. That mismatch can mislead users and reviewers about data flows and functionality, increasing privacy and trust risk because user-provided images may drive broader internet lookups and third-party content exposure than expected.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill lacks a clear user-facing warning that provided images, URLs, or Base64 content may be sent to Baidu for processing. Because images can contain sensitive personal, biometric, location, or proprietary information, omission of this disclosure creates a significant privacy and compliance risk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill declares capabilities that require environment-variable access and outbound network use, but it does not explicitly scope or disclose those permissions. This weakens reviewability and can cause the agent to access secrets or external services without clear operator approval, especially because the skill accepts arbitrary local paths, URLs, and Base64 input.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The entire skill description and the prescribed user prompt are written only in Chinese, with no indication that users may choose another language or that the skill is intentionally restricted to a Chinese-only audience. Under the stated policy, forcing a specific language without opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The activation text says the skill should trigger whenever a user asks to identify image subjects, labels, or scenes, which is broad and underspecified. Over-broad triggering can cause the skill to activate in contexts where users did not intend external image processing or API use, raising privacy and consent concerns.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script transmits user-supplied image content, including local files and downloaded remote images, to Baidu's external API without any explicit runtime consent or privacy warning. Users may provide sensitive images assuming local-only processing, creating a privacy and compliance risk if personal, confidential, or regulated data is sent off-device.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
96% confidence
Finding

The code sends image data to an external service over the network. In this skill's context, that behavior is core to the feature, but it still represents a genuine data-exposure boundary because potentially sensitive user images leave the local environment and are processed by a third party.

Content

Scanner excerpt · scripts/image_recognize.py (reported line 130)May include surrounding context.

python
}

    try:
        response = requests.post(api_url, json=payload, headers=headers, timeout=30)
        response.raise_for_status()
        result = response.json()

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill goes beyond simple image recognition and also retrieves and prints 'similar image' search results from external data returned by the provider. This expands the feature scope and can expose users to unexpected third-party URLs/content and additional data processing that was not clearly described in the skill metadata.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The natural-language description, CLI description, and printed output are all fixed in Chinese, which imposes a specific language on users without opt-in. Under the policy, forcing a language or locale without offering user choice can be a natural-language policy violation unless clearly justified as region-specific.

Content

No source excerpt is available for this finding.