Back to skill

Security audit

Openai Image Gen

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but it can send the OpenAI API key and prompts to an undocumented custom endpoint and writes an unescaped local HTML gallery.

Review or patch this skill before installing. Use it only with a clean environment where OPENAI_BASE_URL and OPENAI_API_BASE are unset or intentionally trusted, avoid confidential prompts, choose an explicit --out-dir when needed, and be cautious opening or hosting the generated index.html until prompt content is escaped.

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/gen.py:27
Finding

API Credentials and Prompts Can Be Transmitted to an Arbitrary Configured Endpoint

Content
View full analysis
str: base = ( os.environ.get("OPENAI_BASE_URL") or os.environ.get("OPENAI_API_BASE") or "https://api.openai.com" ).rstrip("/") if base.endswith("/v1"): return f"{base}/images/generations" return f"{base}/v1/images/generations" ``` ```python def _post_json(url: str, api_key: str, payload: dict, timeout_s: int) -> dict: body = json.dumps(payload).encode("utf-8") req = urllib.request.Request( url, data=body, headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, method="POST", ) ``` ### Technical Analysis The Skill legitimately needs to send prompts and an API credential to the OpenAI Images API. However, `_api_url()` permits the destination to be replaced entirely through `OPENAI_BASE_URL` or `OPENAI_API_BASE`. No validation restricts the configured endpoint to an approved hostname or requires HTTPS. `_post_json()` subsequently sends the API key as a Bearer credential and places the image-generation prompt in the request body. Consequently, a poisoned or incorrectly configured environment can redirect both values to an untrusted server. This behavior exceeds the minimum privilege needed when the supplied credential is specifically an OpenAI API key. Support for OpenAI-compatible endpoints may be intentional, but credentials should be scoped to those endpoints and the change in trust boundary should be explicit. The current implementation can also accept an `http://` endpoint, permitting plaintext interception of the credential and prompt. ### Attack Path 1. An attacker compromises a launcher, shell profile, task configuration, development envi ...[truncated 1397 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/gen.py:141
Finding

Stored HTML Injection Through Unescaped Image Prompts

Content
View full analysis
") html.append(f"") html.append(f"
text
{it['prompt']}
") html.append("") ``` ### Technical Analysis The `--prompt` argument is user-controlled and is stored in each item without sanitization. `_write_index()` then interpolates the prompt directly into an HTML document. Because HTML-sensitive characters are not escaped, a prompt can terminate the intended `
text
` element and inject arbitrary markup or JavaScript. For example, a prompt containing the following value would create an executable script in the generated gallery:

```html
text
```

The injected content persists in `index.html` and executes when the user opens that generated file. The random built-in prompts do not contain active markup, but the documented `--prompt` option makes attacker-controlled input a supported code path.

The generated filenames are derived through `_slug()` and therefore do not provide the same direct injection path. The confirmed issue is the unescaped prompt inserted into the `
text
` element.

### Attack Path

1. An attacker supplies or persuades the user to use a malicious prompt containing HTML or JavaScript.
2. The user invokes the Skill with that value through `--prompt`.
3. The prompt is sent to the image service and then added to the `items` collection.
4. `_write_index()` inserts the prompt into `index.html` without HTML escaping.
5. The user opens the generated gallery as instructed by `SKILL.md`.
6. The browser parses the injected markup and executes any injected script in the gallery's origin context.

I
...[truncated 1041 chars]
Remediation
View remediation
") html_lines.append(f"") html_lines.append(f"
text
{safe_prompt}
") html_lines.append("") ``` Additional hardening should include: 1. Rename the local `html` list variable to avoid conflicting with the imported `html` module. 2. Escape attribute values as well as visible text, even though current filenames are slug-derived. 3. Add a restrictive Content Security Policy, preferably disabling scripts entirely: ```html ``` 4. Add regression tests using prompts containing `
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill invokes a script that requires an API key from the environment and makes outbound network requests, but the skill metadata does not declare those capabilities. This creates a transparency and consent problem: users or higher-level policy systems cannot accurately assess that running the skill will access secrets and contact an external service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The setup/run instructions do not clearly warn that prompts and generated image requests are sent to the OpenAI Images API. Users may unknowingly transmit sensitive or proprietary prompt content to a third-party service, creating privacy, confidentiality, and compliance risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill says outputs may be written to ~/Projects/tmp/... or ./tmp/..., but it does not clearly emphasize that it creates image, JSON, and HTML artifacts on disk, potentially outside the current directory. This can surprise users, leave residual sensitive content behind, or cause unintended writes in shared or monitored locations.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.