Back to skill

Security audit

Generate images & videos with: Gemini 3 Pro Image (image) + Qwen Wan 2.6 (video) via one API key

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it says, but its optional video download can fetch an unvalidated provider-returned URL and write unlimited data to disk.

Review before installing if you will run the Python client in a sensitive network or low-storage environment. Use it only with prompts and image URLs you are comfortable sending to AIsa, protect the AISA_API_KEY, and avoid the --download option unless you trust the returned media URL and can tolerate a large file write.

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

Warning
Location
scripts/media_gen_client.py:84
Finding

Unvalidated Server-Provided URL Enables Arbitrary Network Requests

Content
View full analysis

Vulnerability Details

File Location: scripts/media_gen_client.py, lines 84–99 and 258–263
Vulnerability Type: Unvalidated remote URL / server-side request forgery
Risk Level: Medium

Vulnerable Code

python
def _download_to_file(url: str, out_path: str, timeout_s: int = 300) -> Dict[str, Any]:
    """
    Download a (possibly signed) URL to local file.
    Designed for OSS signed URLs returned by video generation tasks.
    """
    os.makedirs(os.path.dirname(out_path) or ".", exist_ok=True)
    req = urllib.request.Request(url, headers={"User-Agent": "OpenClaw-Media-Gen/1.0"})
    try:
        with urllib.request.urlopen(req, timeout=timeout_s) as resp, open(out_path, "wb") as f:
            total = 0
            while True:
                chunk = resp.read(1024 * 1024)  # 1MB
                if not chunk:
                    break
                f.write(chunk)
                total += len(chunk)
        return {"success": True, "saved_to": out_path, "bytes": total}
python
if status == "SUCCEEDED" and getattr(args, "download", False):
    video_url = (resp.get("output") or {}).get("video_url") or (resp.get("output") or {}).get("videoUrl")
    if video_url:
        out_path = args.out or _safe_filename("mp4")
        dl = _download_to_file(video_url, out_path)
        resp = {**resp, "download": dl}

Technical Analysis

The video download URL comes from the remote task-status response and is passed directly to urllib.request.urlopen. The code does not validate the URL scheme, destination hostname, resolved IP address, port, or redirect destinations.

Consequently, a compromised or malicious API response could direct the client to an unintended endpoint accessible from the user's execution environment. Potential destinations include loopback interfaces, private-network services, link-local services, or attacker-controlled hosts. Because urllib follows ...[truncated 1770 chars]

Remediation
View remediation

Remediation Suggestions

  • Permit only https download URLs.
  • Maintain an allowlist of documented AISA media-storage hostnames or hostname suffixes.
  • Resolve the hostname before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved IP addresses.
  • Protect against DNS rebinding by ensuring the validated address is the address used for the connection.
  • Disable automatic redirects or validate the scheme, hostname, port, and resolved address of every redirect target.
  • Reject URLs containing unexpected credentials, ports, or malformed hostnames.
  • Require explicit user confirmation when a returned media URL uses an unexpected domain.
  • Consider having the API return an opaque media identifier that is downloaded through a fixed trusted endpoint rather than accepting an arbitrary URL.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/media_gen_client.py:84
Finding

Unbounded Video Download Can Exhaust Local Storage

Content
View full analysis

Vulnerability Details

File Location: scripts/media_gen_client.py, lines 84–99
Vulnerability Type: Unrestricted resource consumption
Risk Level: Medium

Vulnerable Code

python
def _download_to_file(url: str, out_path: str, timeout_s: int = 300) -> Dict[str, Any]:
    """
    Download a (possibly signed) URL to local file.
    Designed for OSS signed URLs returned by video generation tasks.
    """
    os.makedirs(os.path.dirname(out_path) or ".", exist_ok=True)
    req = urllib.request.Request(url, headers={"User-Agent": "OpenClaw-Media-Gen/1.0"})
    try:
        with urllib.request.urlopen(req, timeout=timeout_s) as resp, open(out_path, "wb") as f:
            total = 0
            while True:
                chunk = resp.read(1024 * 1024)  # 1MB
                if not chunk:
                    break
                f.write(chunk)
                total += len(chunk)
        return {"success": True, "saved_to": out_path, "bytes": total}

Technical Analysis

The download loop writes data until the remote endpoint closes the response. Although the transfer uses one-megabyte chunks and a timeout, no maximum response or output-file size is enforced. The code also does not inspect Content-Length before beginning the download.

A socket timeout does not provide a reliable total-transfer limit: a server that continuously sends data can keep the connection active while causing the output file to grow until available storage is exhausted. The destination file is opened directly rather than through a temporary file, so failed or interrupted downloads can leave partial output in place.

Attack Path

  1. A malicious or compromised task-status service returns a video URL controlled by the attacker.
  2. The user invokes video-wait --download.
  3. The client opens the returned URL and starts writing its response to the output path.
  4. The endpoint supplies an extremely large re ...[truncated 772 chars]
Remediation
View remediation

Remediation Suggestions

  • Define a conservative, configurable maximum download size appropriate for generated videos.
  • Reject responses whose declared Content-Length exceeds that limit.
  • Track the number of bytes received and terminate the transfer immediately if the limit is crossed, even when Content-Length is missing or incorrect.
  • Apply both per-operation and connection/read timeouts rather than relying solely on socket inactivity.
  • Download into a securely created temporary file and atomically rename it only after successful validation.
  • Delete partial files when a timeout, size violation, network error, or validation failure occurs.
  • Verify the response status and expected media content type before writing the body.
  • Where practical, check available filesystem capacity before starting the download and reserve a safety margin.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (17)

Tainted flow: 'req' from os.environ.get (line 65, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/media_gen_client.py (reported line 67)May include surrounding context.

python
req = urllib.request.Request(url, data=data, headers=all_headers, method=method.upper())
    try:
        with urllib.request.urlopen(req, timeout=timeout_s) as resp:
            raw = resp.read().decode("utf-8")
            return json.loads(raw) if raw else {}
    except urllib.error.HTTPError as e:

Tainted flow: 'req' from os.environ.get (line 65, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The downloader fetches an arbitrary URL returned by the remote video task API and writes the response to disk without validating the scheme, host, or content size. If the upstream service is compromised or manipulated, this can trigger SSRF-like outbound requests from the local machine and unbounded downloads, potentially exposing internal network reachability or causing resource exhaustion.

Content

Scanner excerpt · scripts/media_gen_client.py (reported line 93)May include surrounding context.

python
os.makedirs(os.path.dirname(out_path) or ".", exist_ok=True)
    req = urllib.request.Request(url, headers={"User-Agent": "OpenClaw-Media-Gen/1.0"})
    try:
        with urllib.request.urlopen(req, timeout=timeout_s) as resp, open(out_path, "wb") as f:
            total = 0
            while True:
                chunk = resp.read(1024 * 1024)  # 1MB

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill declares it requires an environment variable and clearly instructs users to make authenticated network requests, but it does not declare an explicit tool/permission scope such as allowed-tools or permissions. That creates a governance gap: an agent may gain network and secret access without a transparent least-privilege declaration, increasing the chance of unintended external calls using the API key.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This markdown file contains core usage instructions and capability descriptions in Chinese, which imposes a specific language on users. The policy allows locale constraints only when clearly documented and justified, or when users are given a choice; neither is present here.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

This example instructs sending user prompts and an Authorization bearer token to an external third-party service. External transmission is expected for a media-generation skill, but it still creates a real data-exposure surface because prompts, referenced content, and API credentials are sent off-platform to a remote endpoint.

Content

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

文档:google-gemini-chat(GenerateContent)见 https://aisa.mintlify.app/api-reference/chat/chat-api/google-gemini-chat.md。

curl 示例(返回 inline_data 时为图片)

bash
curl -X POST "https://api.aisa.one/v1/models/gemini-3-pro-image-preview:generateContent" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

This curl example performs an authenticated POST to a third-party API using the AISA_API_KEY and user-supplied prompt data. In context, that is the intended function of the skill, but it is still a true external-transmission risk because sensitive prompts or account-billed requests could be sent outside the local environment.

Content

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

curl 示例(返回 inline_data 时为图片)

bash
curl -X POST "https://api.aisa.one/v1/models/gemini-3-pro-image-preview:generateContent" \
  -H "Authorization: Bearer $AISA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

This example sends prompts, an image URL, and an authorization token to an external service to create an asynchronous video-generation task. The risk is real because third-party URLs and user content are disclosed externally, and misuse could incur charges or expose sensitive prompt content, even though the behavior matches the skill's advertised purpose.

Content

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

文档:video-generation 见 https://aisa.mintlify.app/api-reference/aliyun/video/video-generation.md。

bash
curl -X POST "https://api.aisa.one/apis/v1/services/aigc/video-generation/video-synthesis" \
  -H "Authorization: Bearer $AISA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-DashScope-Async: enable" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

Polling task status with an Authorization header is another authenticated external call to the provider. Although less sensitive than content creation, it still exposes account-linked metadata and uses a secret over the network, so it is part of the skill's external attack surface.

Content

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

文档:task 见 https://aisa.mintlify.app/api-reference/aliyun/video/task.md。

bash
curl "https://api.aisa.one/apis/v1/services/aigc/tasks?task_id=YOUR_TASK_ID" \
  -H "Authorization: Bearer $AISA_API_KEY"

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

md
OpenClaw Media Gen - AIsa API Client

Image:
  - Gemini GenerateContent: POST https://api.aisa.one/v1/models/{model}:generateContent

Video:
  - Wan 2.6 async task:

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

md
OpenClaw Media Gen - AIsa API Client

Image:
  - Gemini GenerateContent: POST https://api.aisa.one/v1/models/{model}:generateContent

Video:
  - Wan 2.6 async task:

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 · scripts/media_gen_client.py (reported line 6)May include surrounding context.

python
OpenClaw Media Gen - AIsa API Client

Image:
  - Gemini GenerateContent: POST https://api.aisa.one/v1/models/{model}:generateContent

Video:
  - Wan 2.6 async task:

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 · scripts/media_gen_client.py (reported line 10)May include surrounding context.

python
OpenClaw Media Gen - AIsa API Client

Image:
  - Gemini GenerateContent: POST https://api.aisa.one/v1/models/{model}:generateContent

Video:
  - Wan 2.6 async task:

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 · scripts/media_gen_client.py (reported line 11)May include surrounding context.

python
OpenClaw Media Gen - AIsa API Client

Image:
  - Gemini GenerateContent: POST https://api.aisa.one/v1/models/{model}:generateContent

Video:
  - Wan 2.6 async task:

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 · scripts/media_gen_client.py (reported line 28)May include surrounding context.

python
OpenClaw Media Gen - AIsa API Client

Image:
  - Gemini GenerateContent: POST https://api.aisa.one/v1/models/{model}:generateContent

Video:
  - Wan 2.6 async task:

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 · scripts/media_gen_client.py (reported line 29)May include surrounding context.

python
OpenClaw Media Gen - AIsa API Client

Image:
  - Gemini GenerateContent: POST https://api.aisa.one/v1/models/{model}:generateContent

Video:
  - Wan 2.6 async task:

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This markdown file documents networked operations to a third-party API and an automatic download flow that saves an MP4, but it provides no user-facing warning about data being sent externally or files being written to disk. For markdown files, SQP-2 applies when behavior affecting privacy or user data/system integrity is not disclosed.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The skill description and usage headings are written in Chinese, which can constitute a language/locale policy issue when no user choice or justification is provided. The file does not indicate that the skill is intentionally region-specific or that alternative language support is available.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.