Back to skill

Security audit

AI Media Generation En

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a real AIsa media-generation client, but its optional video download can make the user's machine fetch an unvalidated URL returned by the external service.

Install only if you are comfortable sending prompts, reference image URLs, task IDs, and your AIsa API key to AIsa. Prefer AISA_API_KEY over --api-key, avoid sensitive prompts or private image URLs, choose output paths carefully, and be cautious with --download because it fetches whatever video URL the service returns and may overwrite or create local files.

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:79
Finding
Unvalidated Server-Provided URL Enables Arbitrary Resource Retrieval## Vulnerability Details **File Location**: `scripts/media_gen_client.py:79-101`, with the untrusted download URL consumed at `scripts/media_gen_client.py:265-270` **Vulnerability Type**: Unrestricted URL fetch / client-side SSRF **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} except Exception as e: return {"success": False, "error": str(e), "url": url, "saved_to": out_path} ``` ```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 originates in the remote API response and is passed directly to `urllib.request.urlopen`. The implementation does not validate the URL scheme, hostname, resolved IP address, port, or redirect chain. Cross-domain downloads may be necessary because media-generation services commonly return signed object-storage URLs. However, unrestricted URL retriev ...[truncated 1850 chars]
Remediation
## Remediation Suggestions 1. Permit only `https` download URLs. 2. Reject URLs containing embedded credentials. 3. Resolve the hostname before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved IP ranges for both IPv4 and IPv6. 4. Validate every redirect target rather than validating only the initial URL. 5. Prefer an allowlist of documented AIsa object-storage domains where operationally possible. 6. Restrict destination ports to expected HTTPS ports. 7. Apply a maximum response size and validate the response content type before writing it as a video. 8. Consider requiring explicit user confirmation when the returned download host is outside a trusted allowlist.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/media_gen_client.py:30
Finding
API Key Can Be Exposed Through Command-Line Arguments## Vulnerability Details **File Location**: `scripts/media_gen_client.py:30-34`, with the command-line option declared at `scripts/media_gen_client.py:288` **Vulnerability Type**: Sensitive credential exposure through process arguments **Risk Level**: Low ### Vulnerable Code ```python def _get_api_key(explicit: Optional[str] = None) -> str: api_key = explicit or os.environ.get("AISA_API_KEY") if not api_key: raise ValueError("AISA_API_KEY is required (env or --api-key).") return api_key ``` ```python p.add_argument("--api-key", help="Override AISA_API_KEY") ``` ### Technical Analysis The client allows an AIsa API key to be supplied directly through `--api-key`. Command-line arguments may be exposed through shell history, process inspection tools, execution telemetry, terminal session recordings, diagnostic reports, or automation logs. The documented `AISA_API_KEY` environment-variable mechanism reduces this risk, but the additional command-line option encourages a less secure secret-delivery method. Sending the key in the HTTPS `Authorization` header to the declared AIsa service is necessary for the Skill's functionality; accepting it as a visible process argument is not. ### Attack Path 1. A user runs the client with `--api-key` followed by a valid credential. 2. The full command is retained in shell history, automation logs, telemetry, or a process listing visible to another local principal. 3. Another user or system with access to that record obtains the API key. 4. The exposed key is reused against the AIsa API. 5. The attacker consumes the account's service quota, generates billable media, or accesses operations permitted by that credential. ### Impact Assessment An exposed key provides the same AIsa API privileges assigned to that credential. Likely consequences include unauthorized API usage, quota consumption, and financial charges. The code does not hardcode, print, or inten ...[truncated 153 chars]
Remediation
## Remediation Suggestions 1. Remove the `--api-key` command-line option. 2. Continue supporting `AISA_API_KEY`, or integrate with a protected credential store. 3. If interactive entry is required, use a hidden prompt such as `getpass.getpass`. 4. For automation, support reading the secret from a permission-restricted file descriptor or standard input. 5. Ensure exceptions, debug logs, and HTTP diagnostics redact authorization headers. 6. Document credential rotation and advise users to revoke any key previously exposed in command history or logs.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (19)

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

Critical
Category
Data Flow
Content
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:
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

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

Critical
Category
Data Flow
Content
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
Confidence
90% confidence
Finding
The downloader fetches an arbitrary URL returned by the remote task API and writes the response to disk without validating scheme, host, content type, or size. If the upstream service is compromised or returns attacker-controlled signed URLs, this can enable SSRF-style access from the local machine to internal resources, or disk exhaustion via oversized downloads.

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill declares required environment access and documents network calls to external APIs, but it does not declare an explicit tool scope such as permissions or allowed-tools. That omission weakens least-privilege controls and can cause agents or users to invoke the skill without a clear understanding of its network and secret-handling behavior.

External Transmission

Medium
Category
Data Exfiltration
Content
Documentation: `google-gemini-chat` (GenerateContent) at `https://aisa.mintlify.app/api-reference/chat/chat-api/google-gemini-chat.md`

### curl Example (returns inline_data for images)

```bash
curl -X POST "https://api.aisa.one/v1/models/gemini-3-pro-image-preview:generateContent" \
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
OpenClaw Media Gen - AIsa API Client

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

Video:
  - Wan 2.6 async task:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
OpenClaw Media Gen - AIsa API Client

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

Video:
  - Wan 2.6 async task:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
OpenClaw Media Gen - AIsa API Client

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

Video:
  - Wan 2.6 async task:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
OpenClaw Media Gen - AIsa API Client

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

Video:
  - Wan 2.6 async task:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
OpenClaw Media Gen - AIsa API Client

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

Video:
  - Wan 2.6 async task:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
OpenClaw Media Gen - AIsa API Client

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

Video:
  - Wan 2.6 async task:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
OpenClaw Media Gen - AIsa API Client

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

Video:
  - Wan 2.6 async task:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
OpenClaw Media Gen - AIsa API Client

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

Video:
  - Wan 2.6 async task:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
OpenClaw Media Gen - AIsa API Client

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

Video:
  - Wan 2.6 async task:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
OpenClaw Media Gen - AIsa API Client

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

Video:
  - Wan 2.6 async task:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Low
Confidence
86% confidence
Finding
This markdown file instructs users to set an API credential and submit prompts and image URLs to a third-party API, then optionally download generated output, but it does not include any user-facing warning about sending content to an external service or possible billing. For markdown files, missing warnings about behaviors affecting privacy or user data are in scope.

Missing User Warnings

Low
Confidence
86% confidence
Finding
The skill documentation states that the client script automatically parses and saves returned image data to a file. Because this markdown file documents behavior that writes to the local filesystem, it should explicitly warn users about that side effect so they understand files will be created locally.

Missing User Warnings

Low
Confidence
91% confidence
Finding
The documented `video-wait --download --out out.mp4` behavior causes a file to be written locally, but the markdown does not include an explicit caution about filesystem modification. For markdown files, user-facing documentation should warn about behaviors that affect user data or system state.

Missing User Warnings

Low
Confidence
89% confidence
Finding
The code writes generated image bytes directly to a local path via `open(out_path, "wb")`, but there is no prompt, warning, or nearby comment disclosing that the command will create or overwrite a file. For a code file, filesystem writes are safety-relevant operations that should have some visible disclosure unless clearly warned elsewhere.

Missing User Warnings

Low
Confidence
87% confidence
Finding
When `--download` is used, the code downloads the generated video and saves it to disk through `_download_to_file`, but there is no explicit log or warning before performing the write. Although the flag implies download behavior, the code lacks a visible disclosure about creating a local file at the chosen path.

Static analysis

No suspicious patterns detected.