Back to skill

Security audit

Taizi Alicloud Ai Image

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent DashScope image-generation helper, but it can upload arbitrary local files as reference images without containment or clear warning.

Review before installing. Use this only in a sandbox or workspace with limited readable files, avoid sensitive prompts or reference images, do not pass arbitrary local paths as reference_image, and pin/review the DashScope dependency before use. The skill should be tightened to accept only validated image files from an approved input directory and to clearly disclose uploads to DashScope.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_image.py:83
Finding
Arbitrary Local File Disclosure Through Reference Image Input## Vulnerability Details **File Location**: `scripts/generate_image.py`, lines 83-109 **Vulnerability Type**: Unrestricted local file read and external transmission **Risk Level**: High ### Vulnerable Code ```python def resolve_reference_image(value: str) -> Any: if value.startswith("http://") or value.startswith("https://"): return value path = Path(value) if path.exists(): return path.read_bytes() return value def call_generate(req: dict[str, Any]) -> dict[str, Any]: prompt = req.get("prompt") if not prompt: raise ValueError("prompt is required") messages = [{"role": "user", "content": [{"text": prompt}]}] reference_image = req.get("reference_image") if reference_image: messages[0]["content"].insert( 0, {"image": resolve_reference_image(reference_image)} ) response = ImageGeneration.call( model=MODEL_NAME, messages=messages, size=req.get("size", DEFAULT_SIZE), api_key=os.getenv("DASHSCOPE_API_KEY"), negative_prompt=req.get("negative_prompt"), style=req.get("style"), seed=req.get("seed"), ) ``` ### Technical Analysis The caller-controlled `reference_image` field is interpreted as a local filesystem path whenever that path exists. The script reads the entire file without verifying that it is an image, restricting it to an approved directory, checking symlink traversal, imposing a size limit, or requesting confirmation. The resulting bytes are inserted into `messages` and passed to the external DashScope SDK. Consequently, any local file readable by the process can be treated as a reference image and transmitted to the provider. Supporting reference images is necessary for the declared functionality, but unrestricted access to the entire readable filesystem exceeds the minimum privilege required. ### Attack Path 1. An attacker obt ...[truncated 1024 chars]
Remediation
## Remediation Suggestions - Permit local reference images only from a dedicated, explicitly approved input directory. - Resolve the requested path with `Path.resolve()` and verify that it remains beneath the approved directory using `Path.is_relative_to()` or an equivalent safe containment check. - Reject symbolic links or validate the fully resolved target to prevent symlink-based directory escape. - Validate image content using an image decoder rather than trusting the filename extension. - Allowlist supported image formats and enforce strict file-size and pixel-dimension limits. - Reject special files, directories, devices, sockets, and other non-regular files. - Require explicit user confirmation before uploading a local file to an external service. - Consider accepting only HTTPS reference URLs or previously uploaded file identifiers instead of arbitrary local paths.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_image.py:126
Finding
Unvalidated Remote Image URL Retrieval## Vulnerability Details **File Location**: `scripts/generate_image.py`, lines 126-135 **Vulnerability Type**: Unrestricted URL fetching and resource exhaustion **Risk Level**: Medium ### Vulnerable Code ```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()) def download_image_base64(image_url: str) -> str: import base64 with urllib.request.urlopen(image_url) as response: return base64.b64encode(response.read()).decode("utf-8") ``` ### Technical Analysis The script retrieves the URL returned by the remote image-generation service without validating its scheme, hostname, resolved address, redirects, content type, response size, or download duration. Calls to `response.read()` consume the entire response without an upper bound. If the upstream response is compromised or malformed, the URL can potentially point to an internal service, loopback address, local resource supported by the URL handler, or an indefinitely large response. Redirects may also move an initially acceptable URL to a prohibited destination. In `--b64` mode, the retrieved content is Base64-encoded and printed. Base64 is not encryption and does not protect sensitive content. The encoding behavior is expected for inline image output, but it amplifies the consequences of trusting an arbitrary response URL. ### Attack Path 1. A compromised provider, intercepted SDK response, malicious test double, or other upstream manipulation supplies an attacker-controlled `image_url`. 2. The script passes the URL directly to `urllib.request.urlopen()`. 3. The process follows the destination or redirects without validating the final endpoint. 4. The script reads the complete response into memory. 5. The content is either written to the selected output path or emit ...[truncated 576 chars]
Remediation
## Remediation Suggestions - Accept HTTPS URLs only and reject all other schemes. - Allowlist the documented DashScope image-storage domains. - Resolve the hostname and reject loopback, private, link-local, multicast, reserved, and unspecified addresses. - Repeat scheme, host, and address validation after every redirect, or disable redirects entirely. - Configure explicit connection and read timeouts. - Stream responses in bounded chunks instead of calling unbounded `response.read()`. - Enforce a maximum image size and abort when `Content-Length` or streamed bytes exceed it. - Validate the response content type and decode it as a supported image before saving or encoding it. - Avoid printing arbitrary fetched content unless inline output was explicitly requested and validated.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:15
Finding
Unpinned Third-Party DashScope Dependency## Vulnerability Details **File Location**: `SKILL.md`, lines 15-19 **Vulnerability Type**: Unpinned dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash python3 -m venv .venv . .venv/bin/activate python -m pip install dashscope ``` ### Technical Analysis The installation instructions request the latest available `dashscope` package and its transitive dependencies without a reviewed version constraint, lockfile, or package integrity hashes. The exact code installed can therefore change over time without any change to this skill. A virtual environment limits contamination of the system Python installation, but it does not prevent package installation hooks or imported dependency code from executing with the user's permissions. This creates a mutable software supply-chain boundary and prevents reproducible review. No evidence in the audited project establishes that the current `dashscope` package is malicious. The issue is the unsafe and non-reproducible dependency acquisition practice. ### Attack Path 1. A user follows the documented installation command. 2. `pip` resolves the latest available DashScope release and mutable transitive dependency versions. 3. A compromised future release, compromised package account, or malicious transitive dependency is downloaded. 4. Package installation or subsequent import executes the dependency code with the user's permissions. 5. That code can access the same files, credentials, environment variables, and network capabilities available to the skill process. ### Impact Assessment A compromised dependency could execute arbitrary code under the invoking user's account. This could expose `DASHSCOPE_API_KEY`, Alibaba Cloud credentials, workspace files, generated media, and other user-accessible data. The scope is limited by the invoking user's operating-system privileges and environmental isolation. Use of a virtual environment reduces package-management ...[truncated 82 chars]
Remediation
## Remediation Suggestions - Pin DashScope to a reviewed exact version, for example with `dashscope==X.Y.Z`. - Maintain a lockfile that pins all transitive dependencies. - Use hash-checked installations, such as `pip install --require-hashes -r requirements.txt`. - Retrieve packages only from an explicitly configured trusted package index. - Scan pinned dependencies for known vulnerabilities and review updates before adoption. - Document a controlled update process and test dependency upgrades in an isolated environment. - Where practical, run the skill in a sandbox with restricted filesystem and network access.
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (8)

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
86% confidence
Finding
The skill documents capabilities that involve environment access, file I/O, and external network use, but it does not declare any explicit tool scope or permissions boundary. In an agent environment, this weakens least-privilege controls and can allow the skill to be invoked with broader capabilities than its stated purpose requires, increasing the chance of unintended data access or exfiltration.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documentation explains local saving behavior and external API usage but does not clearly warn that prompts and optional reference images are sent to the third-party DashScope service. Users or downstream agents may therefore provide sensitive text or images without understanding they will be transmitted off-platform, creating privacy, compliance, and data-handling risks.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The skill’s primary purpose is image generation, but it also instructs the agent to use a separate messaging capability to deliver files over Telegram. This expands the operational scope from content generation to outbound communication, creating a path for data egress or misdelivery to the wrong recipient if metadata is mishandled or the instruction is reused in other contexts.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The script sends the user prompt and, when provided, a reference image to the DashScope API via ImageGeneration.call. There is no explicit runtime disclosure that user-supplied content will be transmitted to an external service, beyond the module docstring naming DashScope, so this network/data-transfer behavior lacks a clear warning.

Missing User Warnings

Low
Confidence
77% confidence
Finding
This code creates parent directories and writes downloaded image bytes to the specified output path, but the write operation itself has no confirmation prompt or user-facing log message. Although the CLI help mentions an output path, the actual file write is silent, which meets the rule's missing-disclosure criteria for code files.

Static analysis

No suspicious patterns detected.