Back to skill

Security audit

GLM-Image-Gen

Security checks for vulnerabilities and agentic risk

Overview

This image-generation skill is mostly coherent, but its optional save feature downloads an API-provided URL without enough validation or size limits.

Review this before installing if you plan to use --save. The core cloud image generation behavior is disclosed, but prompts and optional user IDs go to ZhiPu, and saved images are downloaded from a remote URL chosen by the API response. Avoid sensitive prompts, use a dedicated API key with limited exposure, and save only to non-critical new filenames until the download path has stricter validation and overwrite protection.

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
scripts/glm_image_cli.py:131
Finding

Unvalidated Server-Provided Image URL Enables Client-Side SSRF and Unbounded Downloads

Content
View full analysis

Vulnerability Details

File Location: scripts/glm_image_cli.py, lines 131–139 and 310–316
Vulnerability Type: Unrestricted URL retrieval, client-side SSRF, and unbounded response buffering
Risk Level: Medium

Vulnerable Code

python
def download_image(url: str, save_path: str) -> bool:
    """Download image from URL to local file."""
    try:
        with urllib.request.urlopen(url, timeout=60) as response:
            with open(save_path, "wb") as f:
                f.write(response.read())
        return True
    except Exception:
        return False

The function is invoked with a URL obtained directly from the remote API response:

python
# Download image if --save specified
saved_file = None
if result["ok"] and args.save and result.get("image_url"):
    if download_image(result["image_url"], args.save):
        saved_file = os.path.abspath(args.save)
    else:
        result["ok"] = False
        result["error"] = {
            "code": "DOWNLOAD_FAILED",
            "message": f"Failed to download image to {args.save}",
        }

Technical Analysis

The generated image URL is extracted from the remote API response and passed directly to urllib.request.urlopen(). The implementation does not validate:

  • The URL scheme or destination hostname.
  • Whether the resolved address is loopback, link-local, private, or reserved.
  • Whether redirects lead to a different or prohibited destination.
  • The response content type or whether the content is actually an image.
  • The response size before calling response.read().
  • Whether an existing destination file may be overwritten.

As a result, a compromised API response, compromised upstream service, or malicious redirect could cause the client to initiate requests to unintended network locations. Because urllib follows redirects, validating only the initial API endpoint would not protect the subsequent ...[truncated 2460 chars]

Remediation
View remediation

Remediation Suggestions

  1. Permit only https image URLs and reject URLs containing embedded credentials or unsupported schemes.
  2. Maintain an explicit allowlist of trusted image-storage hostnames used by the ZhiPu service.
  3. Resolve the hostname before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved IP ranges for both IPv4 and IPv6.
  4. Disable automatic redirects or validate the scheme, hostname, resolved address, and port after every redirect.
  5. Verify that the response has an expected image content type, such as image/png, image/jpeg, or another explicitly supported format.
  6. Stream the response in bounded chunks instead of using an unrestricted response.read().
  7. Enforce a conservative maximum download size using both Content-Length and an actual byte counter while streaming.
  8. Download into a temporary file in the destination directory, validate the image format, and atomically rename it after successful validation.
  9. Refuse to overwrite existing files by default or require an explicit overwrite option.
  10. Preserve and report specific download errors rather than suppressing every exception, while ensuring sensitive values are not included in error output.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (6)

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

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

md
4. **IF API fails** — Display the error message and STOP immediately
5. **NO fallback methods** — Do NOT attempt image generation any other way

### 📋 Output Display Rules / 输出展示规则

After running the script, present the generation result clearly.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill explicitly requires environment access and makes outbound API calls, but it does not declare any explicit tool scope such as allowed tools or permissions. That weakens least-privilege boundaries and can let an agent invoke broader capabilities than users expect, especially in environments where tool scoping is used for enforcement or auditing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill sends user prompts and optional user IDs to an external third-party image API, but the description does not clearly warn users that their content leaves the local environment. This creates a privacy and consent risk because users may unknowingly submit sensitive text or identifiers to an outside service.

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

md
脚本通过 `ZHIPU_API_KEY` 环境变量获取密钥,可与其他智谱技能复用同一个 key。
This script reads the key from the `ZHIPU_API_KEY` environment variable. Reusing the same key across Zhipu skills is optional.

**Get Key / 获取 Key:** Visit [智谱开放平台 API Keys](https://bigmodel.cn/usercenter/proj-mgmt/apikeys) to create or copy your key.

**Setup options / 配置方式(任选一种):**

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

md
脚本通过 `ZHIPU_API_KEY` 环境变量获取密钥,可与其他智谱技能复用同一个 key。
This script reads the key from the `ZHIPU_API_KEY` environment variable. Reusing the same key across Zhipu skills is optional.

**Get Key / 获取 Key:** Visit [智谱开放平台 API Keys](https://bigmodel.cn/usercenter/proj-mgmt/apikeys) to create or copy your key.

**Setup options / 配置方式(任选一种):**

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The documented save feature writes generated images to local disk, but there is no warning about overwriting files, selecting safe paths, or the persistence of generated content. This can lead to accidental data loss or storage of sensitive/generated material in unintended locations.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.