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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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
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 45)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 48)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 169)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
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

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

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

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

Content

No source excerpt is available for this finding.

Missing User Warnings

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

Content

No source excerpt is available for this finding.

Missing User Warnings

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

Content

No source excerpt is available for this finding.