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

Content
View full analysis
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
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_image.py:122
Finding

Unvalidated Image URL Enables Server-Side Request Forgery and Unbounded Downloads

Content
View full analysis
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
View remediation
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
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.

Content

Scanner excerpt · scripts/generate_image.py (reported line 176)May include surrounding context.

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

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/generate_image.py (reported line 47)May include surrounding context.

python
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")

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/generate_image.py (reported line 50)May include surrounding context.

python
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")

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/generate_image.py (reported line 197)May include surrounding context.

python
_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)

Undeclared Tool Scope

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.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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.

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 '{

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.