Back to skill

Security audit

Generate product photos for ecommerce

Security checks for vulnerabilities and agentic risk

Overview

This skill appears purpose-built for ProductAI image generation, but it needs review because it handles long-lived API keys and remote downloads with weak safeguards.

Review before installing. Use only the official ProductAI endpoint, avoid pasting long-lived API keys into ordinary chat, rotate the key if it was exposed, and do not submit confidential or rights-restricted images unless ProductAI's handling terms are acceptable. Treat downloaded results as untrusted remote content and monitor ProductAI token usage.

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/setup.py:39
Finding
API Credentials May Be Transmitted to an Unvalidated Custom Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.py:39-41`; `scripts/productai_client.py:30-35` **Vulnerability Type**: Unvalidated credential destination **Risk Level**: Medium ### Vulnerable Code ```python # scripts/setup.py:39-41 api_endpoint = input("API Endpoint [https://api.productai.photo/v1]: ").strip() if not api_endpoint: api_endpoint = "https://api.productai.photo/v1" ``` ```python # scripts/productai_client.py:30-35 self.api_key = api_key self.api_endpoint = api_endpoint.rstrip('/') self.session = requests.Session() self.session.headers.update({ 'x-api-key': api_key, 'Content-Type': 'application/json' }) ``` ### Technical Analysis The setup process accepts an arbitrary API endpoint and stores it without validating its scheme, hostname, port, or embedded credentials. The client then attaches the ProductAI API key to every request made through its session. Although source image URLs are restricted to HTTPS, the configured API endpoint is not subject to equivalent validation. Consequently, it may use plaintext HTTP or point to an unrelated, attacker-controlled host. This creates a credential-disclosure risk because the `x-api-key` header is automatically transmitted to the configured destination. This is an insecure configuration-boundary issue rather than evidence of intentionally malicious behavior. ### Attack Path 1. An attacker persuades a user or administrator to enter an attacker-controlled URL as the API endpoint, or modifies an accessible configuration file. 2. The user invokes image generation, upscaling, or job-status functionality. 3. `ProductAIClient` creates a request to the configured endpoint. 4. The session automatically adds the victim's ProductAI API key as the `x-api-key` header. 5. The attacker-controlled server records the credential. 6. The attacker uses the captured key against the legitimate ProductAI API, subject to the key's permissions and service-side controls. If an HTTP endpoint i ...[truncated 485 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require the endpoint to use HTTPS. 2. Allowlist the official ProductAI API hostname by default. 3. Reject URLs containing embedded user information, fragments, unexpected ports, or malformed hostnames. 4. If custom endpoints are a required feature, display a prominent warning and require explicit confirmation before transmitting credentials. 5. Repeat endpoint validation in `ProductAIClient.__init__` so manually created configuration files cannot bypass setup-time checks. 6. Consider separating credentials by destination and never attach the ProductAI key to hosts outside an explicit allowlist. 7. Document API-key rotation procedures for users who may have configured an untrusted endpoint. Example validation: ```python from urllib.parse import urlparse def validate_api_endpoint(endpoint: str) -> str: parsed = urlparse(endpoint) if parsed.scheme != "https": raise ValueError("The API endpoint must use HTTPS") if parsed.hostname != "api.productai.photo": raise ValueError("Untrusted API endpoint hostname") if parsed.username or parsed.password: raise ValueError("Embedded URL credentials are not allowed") if parsed.port not in (None, 443): raise ValueError("Unexpected API endpoint port") return endpoint.rstrip("/") ``` ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_photo.py:28
Finding
Remote Result Downloads Lack SSRF and Resource-Consumption Controls<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_photo.py:28-36`; equivalent logic in `scripts/upscale_image.py:16-24` and `scripts/batch_generate.py:47-55` **Vulnerability Type**: Unvalidated remote download, SSRF, and unbounded file write **Risk Level**: Medium ### Vulnerable Code ```python def download_image(url: str, output_path: Path) -> None: """Download image from URL to local file.""" print(f"Downloading image to {output_path}...") response = requests.get(url, stream=True, timeout=30) response.raise_for_status() with open(output_path, 'wb') as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk) print(f"✓ Saved to {output_path}") ``` Equivalent download implementations appear in the batch generator and upscaling script. ### Technical Analysis The URL used by these functions originates from the remote API's completed-job response. Unlike source image URLs processed by `ProductAIClient.validate_image_url`, result URLs are downloaded without validation. The downloader: - Does not require HTTPS. - Does not reject loopback, private, link-local, or other special-purpose destinations. - Allows `requests` to follow redirects without validating each redirect target. - Does not restrict downloads to a trusted ProductAI CDN hostname. - Does not validate the response content type. - Does not enforce a maximum response size. - Writes streamed content until the server closes the connection or another error occurs. A compromised API, attacker-controlled custom API endpoint, or compromised upstream response could therefore return a URL targeting a service accessible only from the user's machine. The script would issue a GET request to that destination. A hostile server could also stream a very large response and consume available disk space. The 30-second request timeout does not establish a total download-size limit and does not reliably prevent resource exhaustion where d ...[truncated 1838 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate every result URL before initiating a download. 2. Require HTTPS and, where operationally possible, allowlist the official ProductAI CDN hostname. 3. Resolve hostnames and reject loopback, private, link-local, multicast, reserved, and unspecified IPv4 and IPv6 addresses. 4. Disable automatic redirects or validate the destination of every redirect before following it. 5. Revalidate after DNS resolution and consider DNS-rebinding defenses. 6. Enforce a maximum download size using both `Content-Length` and a cumulative byte counter while streaming. 7. Restrict accepted media types to expected image MIME types. 8. Download to a temporary file in the destination directory and atomically rename it only after successful validation. 9. Consolidate the three duplicate download functions into one hardened implementation. 10. Optionally decode the downloaded data with an image library under resource limits to confirm it is a supported image. Illustrative size control: ```python MAX_DOWNLOAD_SIZE = 25 * 1024 * 1024 total = 0 with open(output_path, "wb") as f: for chunk in response.iter_content(chunk_size=8192): if not chunk: continue total += len(chunk) if total > MAX_DOWNLOAD_SIZE: raise ValueError("Downloaded image exceeds the size limit") f.write(chunk) ``` Redirect handling should use `allow_redirects=False`, inspect each `Location` value, apply the same URL and resolved-address checks, and enforce a small redirect limit. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • Rogue AgentSelf-Modification, Session Persistence
Findings (53)

Credential Access

High
Category
Privilege Escalation
Content
### Filename Sanitization Tests
```bash
✓ "normal.jpg" → "normal.jpg"
✓ "../../../etc/passwd" → "______etc_passwd"
✓ "file/with/slashes.png" → "file_with_slashes.png"
✓ ".hidden" → "_hidden"
✓ "file with spaces.jpg" → "file_with_spaces.jpg"
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
The documented behavior does not fully match what the skill actually requires and implies: it reads local configuration, sends data to an external service, and claims capabilities like adaptive templates and video ads that are not evidenced here. This mismatch can mislead users and orchestrators about data handling and operational scope, resulting in unintended exposure of credentials, local files, or user content.

Context-Inappropriate Capability

Medium
Confidence
98% confidence
Finding
The document explicitly instructs the agent to collect a raw ProductAI API key from the conversation and write it into a local config.json file. Even with 0600 permissions, this is still plaintext credential storage and expands exposure to chat logs, local compromise, backups, or accidental disclosure by other tools reading the workspace.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The instructions normalize programmatic collection and persistence of an API key without warning about secret-handling risks or safer alternatives. In an agent setting, this increases the chance that credentials are captured in transcripts, tool logs, memory, or files beyond the user's expectations.

Intent-Code Divergence

Medium
Confidence
99% confidence
Finding
The example tells the user the API key is 'saved securely' even though it is only written as plaintext JSON with restrictive file permissions. This is misleading and may cause users to overtrust the storage model, reducing caution around backups, endpoint compromise, or other software with access to the file.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The sample conversation shows a user pasting a full API key directly into chat and the agent accepting it without any warning. In LLM-agent environments, chat channels are often logged, cached, or inspectable, so encouraging secret sharing through conversation materially increases credential exposure risk.

External Transmission

Medium
Category
Data Exfiltration
Content
When prompted:
- **API Key:** Paste your key from Step 1
- **API Endpoint:** Press Enter (uses default: `https://api.productai.photo/v1`)
- **Default Model:** Press Enter (uses `nanobanana`)
- **Default Resolution:** Press Enter (uses `1024x1024`)
- **Your Plan:** Enter your plan (`basic`, `standard`, or `pro`)
Confidence
76% confidence
Finding
The guide explicitly configures an external API endpoint, which confirms that data and credentials are sent to a remote service. In this context, external transmission is expected functionality rather than hidden exfiltration, but it is still security-relevant because users are instructed to provide an API key and later transmit image references to a third party without accompanying trust, privacy, or handling guidance.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The quick start encourages users to submit image URLs to ProductAI but does not warn that those URLs, and potentially the linked image contents, are sent to an external third-party service for processing. In a product-photo workflow, users may assume this is routine, but the lack of an explicit privacy notice increases the risk that confidential, pre-release, or customer-owned assets are transmitted off-platform without informed consent.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The README encourages users to submit product images and prompts to ProductAI.photo but does not clearly warn that these inputs are transmitted to an external third-party service. This can mislead users into sending proprietary product assets, unreleased marketing materials, or sensitive prompts off-platform without informed consent, creating confidentiality and compliance risk.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
- Users can use environment variables if preferred: `PRODUCTAI_API_KEY`

**Mitigation:**
- Config file: `chmod 600` (user-only access)
- API key never logged or displayed in output
- Clear documentation warns users to keep keys secure
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Intent-Code Divergence

Medium
Confidence
89% confidence
Finding
The guide explicitly instructs agents to ask users for raw API keys in chat and accept them directly, which increases the chance that secrets are exposed in conversation history, logs, telemetry, screenshots, or downstream tooling. Even if the document says keys should not be logged or displayed, normal agent/platform behavior may still persist user messages, so collecting the secret this way is risky.

Session Persistence

Medium
Category
Rogue Agent
Content
```

- Stored at: `~/.openclaw/workspace/productai/config.json`
- Permissions: `600` (user read/write only)
- Never log or display the API key

### Testing the API Key
Confidence
86% confidence
Finding
The guide instructs storing the API key persistently in ~/.openclaw/workspace/productai/config.json, creating long-lived credential exposure on disk. Although permissions 600 reduce risk, plaintext session persistence still increases impact from local compromise, backups, or accidental file handling, especially for an agent-oriented workspace.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The programmatic setup flow writes a user-provided API key to a local config file without requiring an explicit informed consent step at the time of collection. This creates a secret-at-rest risk: users may provide a credential believing it is used transiently, while it is actually persisted on disk and potentially accessible to other local processes, backups, or later compromise of the host.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill documents shell execution, network access, and local file writes/reads, but does not declare any explicit tool scope or permissions. That increases the chance the skill is invoked with broader capabilities than users expect, enabling unbounded command execution, filesystem modification, and outbound data transfer.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The activation text is broad enough to match many generic image-editing or marketing requests, which can cause the skill to trigger in contexts where users did not intend third-party processing. Overbroad invocation increases the risk of unnecessary data sharing and misuse of network/shell capabilities.

Session Persistence

Medium
Category
Rogue Agent
Content
# ProductAI Integration

ProductAI.photo is an AI-powered service that generates professional product photos from existing images. It enables e-commerce businesses, marketers, and designers to create studio-quality product photography without hiring photographers.

## Quick Start
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.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documentation does not clearly warn that user-provided images, prompts, and possibly job metadata are transmitted to an external third-party service. Without that notice, users may unknowingly submit sensitive or proprietary content, creating privacy, confidentiality, and compliance risks.

External Transmission

Medium
Category
Data Exfiltration
Content
```json
{
  "api_key": "your-api-key-here",
  "api_endpoint": "https://api.productai.photo/v1",
  "default_model": "nanobanana",
  "default_resolution": "1024x1024",
  "plan": "standard"
Confidence
79% confidence
Finding
This skill is designed around transmitting content to an external API endpoint, which is expected behavior, but it still creates a real data-exposure surface. Any image URLs, prompts, generated content, and authentication data involved in requests leave the local environment and become subject to third-party handling and retention.

External Transmission

Medium
Category
Data Exfiltration
Content
All API requests require authentication via the `x-api-key` header:

```bash
curl -H "x-api-key: YOUR_API_KEY" https://api.productai.photo/v1/api/generate
```

**Rate Limiting:** 15 requests per minute per IP address.
Confidence
86% confidence
Finding
The authentication example normalizes sending requests to a third-party API but does not accompany it with any warning about external data transfer or API-key handling considerations. In an agent ecosystem, examples like this can encourage integrations that pass user content externally without informed consent or minimal data-handling safeguards.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The API reference instructs users to send `image_url` values and free-form prompts to a third-party service but does not clearly warn that user-provided image references, prompts, and related metadata leave the local environment and are processed externally. In an agent skill context, this omission can cause unintentional disclosure of sensitive product images, internal URLs, or proprietary marketing data because users may not realize their inputs are transmitted off-platform.

Whitespace Padding

Medium
Category
Prompt Injection
Content
### Request Body

| Field           | Type                   | Required | Description                                                                                                                                                                              |
| --------------- | ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `image_url`     | `string` or `string[]` | Yes      | URL(s) of input image(s). Maximum 2 images.                                                                                                                                              |
| `prompt`        | `string`               | Yes      | Text prompt describing the desired edit/generation.                                                                                                                                      |
Confidence
70% confidence
Finding
Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Whitespace Padding

Medium
Category
Prompt Injection
Content
| Field           | Type                   | Required | Description                                                                                                                                                                              |
| --------------- | ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `image_url`     | `string` or `string[]` | Yes      | URL(s) of input image(s). Maximum 2 images.                                                                                                                                              |
| `prompt`        | `string`               | Yes      | Text prompt describing the desired edit/generation.                                                                                                                                      |
| `model`         | `string`               | Yes      | One of: `gpt-low`, `gpt-medium`, `gpt-high`, `kontext-pro`, `kontext-max`, `nanobanana`, `nanobananapro`, `seedream`                                                                    |
| `output_format` | `string`               | No       | `"png"` (default) or `"jpg"` / `"jpeg"`                                                                                                                                                 |
Confidence
70% confidence
Finding
Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Whitespace Padding

Medium
Category
Prompt Injection
Content
| Field           | Type                   | Required | Description                                                                                                                                                                              |
| --------------- | ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `image_url`     | `string` or `string[]` | Yes      | URL(s) of input image(s). Maximum 2 images.                                                                                                                                              |
| `prompt`        | `string`               | Yes      | Text prompt describing the desired edit/generation.                                                                                                                                      |
| `model`         | `string`               | Yes      | One of: `gpt-low`, `gpt-medium`, `gpt-high`, `kontext-pro`, `kontext-max`, `nanobanana`, `nanobananapro`, `seedream`                                                                    |
| `output_format` | `string`               | No       | `"png"` (default) or `"jpg"` / `"jpeg"`                                                                                                                                                 |
| `aspect_ratio`  | `string`               | No       | `"SQUARE"`, `"LANDSCAPE"`, `"PORTRAIT"`. For `nanobanana`/`nanobananapro` also supports: `"LANDSCAPE_4_3"`, `"LANDSCAPE_5_4"`, `"SQUARE_1_1"`, `"PORTRAIT_4_5"`, `"PORTRAIT_3_4"`, or direct ratios like `"4:3"`, `"9:16"`, etc. |
Confidence
70% confidence
Finding
Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Whitespace Padding

Medium
Category
Prompt Injection
Content
| `image_url`     | `string` or `string[]` | Yes      | URL(s) of input image(s). Maximum 2 images.                                                                                                                                              |
| `prompt`        | `string`               | Yes      | Text prompt describing the desired edit/generation.                                                                                                                                      |
| `model`         | `string`               | Yes      | One of: `gpt-low`, `gpt-medium`, `gpt-high`, `kontext-pro`, `kontext-max`, `nanobanana`, `nanobananapro`, `seedream`                                                                    |
| `output_format` | `string`               | No       | `"png"` (default) or `"jpg"` / `"jpeg"`                                                                                                                                                 |
| `aspect_ratio`  | `string`               | No       | `"SQUARE"`, `"LANDSCAPE"`, `"PORTRAIT"`. For `nanobanana`/`nanobananapro` also supports: `"LANDSCAPE_4_3"`, `"LANDSCAPE_5_4"`, `"SQUARE_1_1"`, `"PORTRAIT_4_5"`, `"PORTRAIT_3_4"`, or direct ratios like `"4:3"`, `"9:16"`, etc. |
| `resolution`    | `string`               | No       | For `nanobanana`/`nanobananapro` only: `"1K"`, `"2K"` (default), or `"4K"`                                                                                                               |
Confidence
70% confidence
Finding
Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Whitespace Padding

Medium
Category
Prompt Injection
Content
| `model`         | `string`               | Yes      | One of: `gpt-low`, `gpt-medium`, `gpt-high`, `kontext-pro`, `kontext-max`, `nanobanana`, `nanobananapro`, `seedream`                                                                    |
| `output_format` | `string`               | No       | `"png"` (default) or `"jpg"` / `"jpeg"`                                                                                                                                                 |
| `aspect_ratio`  | `string`               | No       | `"SQUARE"`, `"LANDSCAPE"`, `"PORTRAIT"`. For `nanobanana`/`nanobananapro` also supports: `"LANDSCAPE_4_3"`, `"LANDSCAPE_5_4"`, `"SQUARE_1_1"`, `"PORTRAIT_4_5"`, `"PORTRAIT_3_4"`, or direct ratios like `"4:3"`, `"9:16"`, etc. |
| `resolution`    | `string`               | No       | For `nanobanana`/`nanobananapro` only: `"1K"`, `"2K"` (default), or `"4K"`                                                                                                               |

### Models & Pricing
Confidence
70% confidence
Finding
Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Static analysis

No suspicious patterns detected.