Back to skill

Security audit

Alibaba Cloud AI Image Zimage Turbo

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a normal Alibaba Cloud image-generation helper, but it can send the user's DashScope API key to an arbitrary endpoint override and download arbitrary returned URLs without validation.

Review before installing. Use this only with trusted requests and trusted environment variables; do not allow untrusted users or prompts to set base_url or DASHSCOPE_BASE_URL. Prefer restricting calls to the official DashScope endpoints, rotate any key used with an untrusted endpoint, and save outputs only to paths you intend to overwrite.

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/generate_image.py:109
Finding
DashScope API Key Can Be Exfiltrated Through an Unrestricted Endpoint Override<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_image.py:109-119` and `scripts/generate_image.py:148-150` **Vulnerability Type**: Arbitrary credential destination / sensitive information disclosure **Risk Level**: High ### Vulnerable Code ```python def _post_json(url: str, api_key: str, payload: dict[str, Any]) -> dict[str, Any]: data = json.dumps(payload, ensure_ascii=False).encode("utf-8") req = urllib.request.Request( url, data=data, headers={ "Content-Type": "application/json", "Authorization": f"Bearer {api_key}", }, method="POST", ) with urllib.request.urlopen(req) as response: body = response.read().decode("utf-8") return json.loads(body) ``` ```python def call_generate(req: dict[str, Any]) -> dict[str, Any]: api_key = os.getenv("DASHSCOPE_API_KEY") if not api_key: raise RuntimeError("DASHSCOPE_API_KEY is not set") base_url = req.get("base_url") or os.getenv("DASHSCOPE_BASE_URL") or DEFAULT_BASE_URL payload = _build_payload(req) resp = _post_json(base_url, api_key, payload) ``` ### Technical Analysis The script loads a DashScope API key from the environment, `.env` files, or `~/.alibabacloud/credentials`. Access to this credential is necessary for the declared image-generation operation. However, the destination receiving that credential can be supplied directly through the request object's `base_url` field or indirectly through the `DASHSCOPE_BASE_URL` environment variable. The script does not validate: - The URL scheme - The destination hostname - The destination port - The API path - Embedded URL user information - Whether redirects remain on an approved origin The `_post_json` function unconditionally attaches the loaded credential as a bearer token to the selected URL. Therefore, a crafted request can cause the user's secret API key and image prompt to be transmitted to an attacker-controlled serve ...[truncated 2076 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove request-level arbitrary endpoint overrides unless they are strictly required. 2. Allowlist the exact documented HTTPS endpoints: - `https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation` - `https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation` 3. Parse URLs with `urllib.parse.urlsplit` and require: - Scheme equal to `https` - An exact approved hostname - No username or password component - No unexpected port - The exact approved API path 4. Disable automatic redirects for authenticated requests, or validate every redirect target and refuse cross-origin redirects before resending the `Authorization` header. 5. Do not derive a credential-bearing endpoint from untrusted request JSON. 6. If custom enterprise endpoints are necessary, require explicit administrator configuration and a separate allowlist rather than accepting arbitrary caller input. 7. Add tests confirming that HTTP URLs, unknown hosts, userinfo URLs, alternate ports, malformed URLs, and cross-origin redirects are rejected. 8. Rotate any API key that may already have been used with an untrusted `base_url`. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_image.py:122
Finding
Unvalidated Image URL Enables Server-Side Request Forgery and Unbounded Downloads<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_image.py:122-131`, `scripts/generate_image.py:152-162`, and `scripts/generate_image.py:164-167` **Vulnerability Type**: Server-side request forgery and unrestricted response download **Risk Level**: Medium ### Vulnerable Code ```python def _extract_image_url(resp: dict[str, Any]) -> str: choices = (((resp.get("output") or {}).get("choices")) or []) if not choices: raise RuntimeError("No choices returned by DashScope") content = (choices[0].get("message") or {}).get("content") or [] for item in content: if isinstance(item, dict) and item.get("image"): return item["image"] raise RuntimeError("No image URL returned by DashScope") ``` ```python output = resp.get("output") or {} choices = output.get("choices") or [] content = (choices[0].get("message") or {}).get("content") if choices else [] image_url = _extract_image_url(resp) return { "image_url": image_url, "width": (resp.get("usage") or {}).get("width"), "height": (resp.get("usage") or {}).get("height"), "prompt": req.get("prompt"), "rewritten_prompt": _extract_text_field(content, "text"), "reasoning": _extract_text_field(content, "reasoning_content"), "request_id": resp.get("request_id"), } ``` ```python def download_image(image_url: str, output_path: Path) -> None: output_path.parent.mkdir(parents=True, exist_ok=True) with urllib.request.urlopen(image_url) as response: output_path.write_bytes(response.read()) ``` ### Technical Analysis The image URL is taken directly from the remote API response and passed to `urllib.request.urlopen` without validation. The downloader does not enforce: - HTTPS - A trusted hostname or CDN domain - A safe resolved IP address - Redirect restrictions - An image media type - A maximum response size - A network timeout - Expected image file signatures A malici ...[truncated 2273 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the returned URL before initiating any network request. 2. Require HTTPS and reject unsupported URL schemes. 3. Allowlist trusted Alibaba Cloud image-delivery or CDN hostnames where the provider's documented behavior permits a stable allowlist. 4. Resolve the hostname and reject all loopback, private, link-local, multicast, reserved, and unspecified IP addresses for both IPv4 and IPv6. 5. Revalidate the destination after every redirect and reject redirects to unapproved origins or prohibited IP ranges. 6. Apply explicit connection and read timeouts. 7. Stream the response in bounded chunks instead of using an unrestricted `response.read()`. 8. Enforce a conservative maximum image size and abort the download when the limit is exceeded. 9. Require an expected image `Content-Type` and verify the downloaded file's signature before accepting it. 10. Download to a temporary file with restrictive permissions, validate it, and atomically move it to the requested output path only after successful verification. 11. Add tests covering private IP addresses, loopback targets, cloud metadata addresses, DNS rebinding scenarios, redirect chains, incorrect content types, and oversized responses. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (12)

Tainted flow: 'image_url' from os.getenv (line 162, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
def download_image(image_url: str, output_path: Path) -> None:
    output_path.parent.mkdir(parents=True, exist_ok=True)
    with urllib.request.urlopen(image_url) as response:
        output_path.write_bytes(response.read())
Confidence
90% confidence
Finding
The script downloads a URL returned by the remote API without validating its scheme, host, or size. If the upstream service is compromised, misconfigured, or redirected via a nonstandard base URL, this could trigger server-side request forgery behavior or local file access attempts through urllib-supported schemes, and can also cause unbounded downloads.

Credential Access

High
Category
Privilege Escalation
Content
def _load_env() -> None:
    _load_dotenv(Path.cwd() / ".env")
    repo_root = _find_repo_root(Path(__file__).resolve())
    if repo_root:
        _load_dotenv(repo_root / ".env")
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
def _load_env() -> None:
    _load_dotenv(Path.cwd() / ".env")
    repo_root = _find_repo_root(Path(__file__).resolve())
    if repo_root:
        _load_dotenv(repo_root / ".env")
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
_load_dashscope_api_key_from_credentials()
    if not os.environ.get("DASHSCOPE_API_KEY"):
        print(
            "Error: DASHSCOPE_API_KEY is not set. Configure it via env/.env or ~/.alibabacloud/credentials.",
            file=sys.stderr,
        )
        print("Example .env:\n  DASHSCOPE_API_KEY=your_key_here", file=sys.stderr)
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill documents capabilities that access environment secrets, the local filesystem, and the network, but it declares no explicit tool scope or permission boundaries. That makes it harder for a caller or platform to constrain execution and increases the chance of unintended secret exposure, file modification, or outbound requests beyond the user’s expectations.

External Transmission

Medium
Category
Data Exfiltration
Content
## Quick start (curl)

```bash
curl -sS 'https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $DASHSCOPE_API_KEY" \
  -d '{
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The request target can be overridden by req['base_url'] or DASHSCOPE_BASE_URL, allowing the skill to send prompts and the Bearer API key to an arbitrary endpoint. In a skill context, this broadens the trust boundary far beyond the declared Alibaba DashScope service and enables credential exfiltration and deceptive downstream responses.

Missing User Warnings

Low
Confidence
82% confidence
Finding
The documented commands write output files and validation artifacts to disk without clearly warning about overwriting existing files or constraining destinations beyond examples. In normal use this is low risk, but it can still cause unintended local file modification or data loss if users reuse paths carelessly or if wrappers substitute user-controlled paths.

Intent-Code Divergence

Low
Confidence
88% confidence
Finding
The manifest and the rest of the file define a narrow text-to-image generation skill using the Z-Image Turbo API. However, the workflow instructs the operator to determine whether an operation is "read-only or mutating" and to run a "read-only query," which does not fit or make sense for an image-generation API and suggests a copied generic cloud-operations workflow rather than the documented behavior.

Context-Inappropriate Capability

Low
Confidence
75% confidence
Finding
The skill's stated purpose is image generation and request/response mapping for Z-Image, but the implementation also searches the current directory, repository root, and `~/.alibabacloud/credentials` for secrets. While this may be convenient for authentication, local credential discovery is an additional capability not mentioned in the manifest description.

Missing User Warnings

Low
Confidence
91% confidence
Finding
This code sends the user-provided prompt and parameters to the external DashScope API, which may transmit user data off-system. While the script name and docstring imply image generation via DashScope, there is no explicit user-facing disclosure at the point of execution or in comments/logging that prompt contents are sent to a remote service.

Missing User Warnings

Low
Confidence
85% confidence
Finding
The script creates directories and writes downloaded image bytes to the provided output path, but it does not emit any confirmation or user-facing notice when performing the file write. The operation is expected for an image-generation tool, yet the code itself lacks explicit disclosure of the write action.

Static analysis

No suspicious patterns detected.