Back to skill

Security audit

GoAI Image Gen

Security checks for vulnerabilities and agentic risk

Overview

This GoAI image-generation skill is purpose-aligned, but it needs Review because remote responses and endpoint settings can affect credentials, network fetches, and local file writes too broadly.

Install only if you trust GoAI and your OpenClaw environment configuration. Avoid setting GOAI_BASE_URL unless you control and trust the endpoint, do not use sensitive local reference images unless you intend to upload them, and prefer a version that pins dependencies and constrains downloads to a safe output directory.

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

Warning
Location
scripts/common.py:95
Finding

Unrestricted API Endpoint Can Expose the GoAI API Key and User Content

Content
View full analysis
None: self.skill_name = skill_name self.base_url = os.environ.get("GOAI_BASE_URL", DEFAULT_BASE_URL).rstrip("/") self.api_key = os.environ.get("GOAI_API_KEY", "") self.last_payload: dict[str, Any] | None = None self.last_media_url = "" self._capabilities: dict[str, Any] | None = None self._http = httpx.Client( timeout=httpx.Timeout(60.0, connect=20.0), follow_redirects=True, ) ``` ```python def _headers(self, auth_mode: str) -> dict[str, str]: headers = {"Accept": "application/json"} if auth_mode == "auth": headers["Authorization"] = f"Bearer {self.api_key}" return headers ``` ```python def json_request( self, method: str, url: str, auth_mode: str, *, query: dict[str, Any] | None = None, body: dict[str, Any] | None = None, ) -> dict[str, Any]: try: response = self._http.request( method, url, headers=self._headers(auth_mode), params=query, json=body, ) ``` ### Technical Analysis `GOAI_BASE_URL` is accepted without validating its scheme or hostname. Authenticated API requests then attach `GOAI_API_KEY` as a bearer token to URLs derived from that value. Consequently, a mistaken, malicious, or externally influenced environment configuration can redirect authenticated requests to an attacker-controlled server. The implementation also permits plaintext `http://` endpoints and enables automatic redirects. This creates two related risks: 1. The bearer credential may be sent directly to an untrusted or plaintext ...[truncated 1720 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/common.py:406
Finding

Backend-Controlled Task Data Enables Arbitrary URL Fetching and Unsafe Output Paths

Content
View full analysis
str: if not media_url: raise GoAIError("download URL is required") output_path = Path(output_name).expanduser() if not output_path.is_absolute(): output_path = (Path.cwd() / output_path).resolve() output_path.parent.mkdir(parents=True, exist_ok=True) try: response = self._http.get(media_url) except httpx.RequestError: raise GoAIError(f"download failed: {media_url}") from None if response.status_code not in {200, 201}: raise GoAIError(f"download failed: {media_url}") output_path.write_bytes(response.content) return str(output_path) ``` ### Technical Analysis The API response controls both `task_id` and the final `image_url`. Neither value is constrained before use. The `task_id` is interpolated into an output filename and subsequently resolved relative to ...[truncated 3037 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
pyproject.toml:5
Finding

Mutable Dependency Resolution Without a Lockfile Creates Supply-Chain Exposure

Content
View full analysis
=0.27,<1", ] ``` ```python os.execvpe( uv_bin, [ uv_bin, "run", "--project", str(skill_dir), "python", str(script_path), *sys.argv[1:], ], os.environ.copy(), ) ``` The Skill documentation states: ```text On first run, uv may create a local environment, install httpx, and download Python if the machine does not already have a usable interpreter. ``` It also states: ```text the dependency set comes only from pyproject.toml and uv.lock ``` However, no `uv.lock` file is present in the audited project. ### Technical Analysis The Skill automatically invokes `uv run`, which may download a Python runtime and resolve third-party dependencies on first execution. The only declared direct dependency uses the broad range `httpx>=0.27,<1`, and the project does not contain the `uv.lock` file referenced by its documentation. As a result, installation is not reproducible. Future executions can resolve different versions of `httpx` and its transitive dependencies than those reviewed during the audit. Package artifacts are selected at runtime rather than from a committed, reviewed lockfile. No malicious, typosquatted, or dependency-confusion package was identified in the current manifest. The risk arises from mutable dependency resolution and the automatic execution of newly downloaded package code. ### Attack Path 1. The Skill is executed on a host without an existing project environment. 2. `bootstrap.py` replaces the current process with `uv run`. 3. `uv` contacts its configured Python and package sources. 4. Because no lockfile exists, `uv` resolves versions satisfying the broad dependency constraint at ...[truncated 703 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill is presented as an image-generation helper, but its documented behavior includes environment bootstrapping and process re-execution via uv/python self-healing. That mismatch can conceal materially different execution behavior from operators, making review and consent weaker and increasing the risk of unexpected code execution paths.

Content

No source excerpt is available for this finding.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
85% confidence
Finding

os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Content

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

python
print(_uv_install_hint(), file=sys.stderr)
        raise SystemExit(1)

    os.execvpe(
        uv_bin,
        [
            uv_bin,

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/bootstrap.py (reported line 61)May include surrounding context.

python
str(script_path),
            *sys.argv[1:],
        ],
        os.environ.copy(),
    )

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill invokes shell commands, uses environment variables, reads and writes local files, and performs network operations, yet the manifest does not declare any tool scope or permission boundaries. This increases the chance of over-broad execution in hosts that rely on manifest-declared permissions for review, policy enforcement, or least-privilege gating.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The manifest description lists many generic verbs such as 'create, generate, draw, edit, render, or make images' and broad nouns like 'photos' and 'posters' without clear exclusion conditions. This can overlap with everyday requests and does not define narrow activation boundaries, increasing the chance of unintended invocation.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
Pass the user's image prompt through as-is unless the user explicitly asks for prompt optimization, prompt polishing, rewriting, translation, or additional creative detail. Do not silently embellish short prompts such as `画一个老虎`.

Do not translate the user's prompt to another language. If the user writes in Chinese, pass Chinese to `--prompt`. If the user writes in English, pass English to `--prompt`. You may strip only lightweight request wrappers such as `帮我`, `给我`, `请`, `生成`, or `画一张`, but do not rewrite the core prompt content.

Examples:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill uploads user-provided local images to a remote API when references are supplied, but it does not require an explicit user-facing warning or confirmation about data transmission. This can lead to accidental exfiltration of local sensitive images, especially if the user only intended local processing.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
- macOS: `brew install uv`
- Windows: `winget install astral-sh.uv`

After `uv` is installed, rerun the same command. Do not ask the user to install Python packages by hand; `uv` is responsible for preparing Python and the skill dependencies.

If execution reports a missing Python module such as `httpx`, do not run `pip install`, `pip install --user`, or `pip install --break-system-packages`. Re-run the skill through `uv`; the dependency set comes only from `pyproject.toml` and `uv.lock`.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill requires always returning a public media URL to the user, but provides no privacy warning or consent step. Generated images may contain sensitive content, and exposing a public URL by default can unintentionally disclose user data or make private creations accessible beyond the local environment.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: httpx has 2 known advisory(ies) (CVE-2021-41945 (Improper Input Validation in httpx); CVE-2021-41945 (Encode OSS httpx <=1.0.0.beta0 is affected by improper input validation in `http)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.