Back to skill

Security audit

pixelhub-api-tools

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Pixelhub API helper, but its setup tells users to paste an API key into chat and store it in source code.

Review before installing. Use this only if you are comfortable sending prompts, media URLs, and task data to Pixelle/Pixelhub. Do not paste API keys into chat or store them in the source file; use the existing Pixelhub_API_KEY environment variable or another secret store, and avoid setting Pixelhub_BASE_URL or --base-url to anything except the intended Pixelle HTTPS service.

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

Error
Location
SKILL.md:20
Finding
API key requested through chat and persisted in source code## Vulnerability Details **File Location**: `SKILL.md:20-24` **Related Location**: `pixelhub_api_runner.py:13`, `pixelhub_api_runner.py:282-284` **Vulnerability Type**: Secret exposure through insecure collection and hardcoded storage **Risk Level**: High ### Vulnerable Code ```markdown 3. Tell the user to copy their own Pixelle API key and send it in chat. 4. After the user sends the key, replace `DEFAULT_API_KEY` in `pixelhub_api_runner.py`. 5. After the key is written, change this file's status line from `PENDING_USER_API_KEY` to `API_KEY_ADDED`. 6. After that, do not ask for the API key again unless the user wants to replace it. ``` The destination in which the instructions require the key to be stored is: ```python DEFAULT_API_KEY = "PENDING_USER_API_KEY" ``` The runner also already supports an environment variable, making source-code persistence unnecessary: ```python p.add_argument( "--api-key", default=os.getenv("Pixelhub_API_KEY", DEFAULT_API_KEY), help="Pixelhub API key", ) ``` ### Technical Analysis The setup instructions explicitly require the user to disclose an API credential in chat and direct the agent to replace a constant in the Python source file with that credential. This creates two persistent secret-exposure surfaces: 1. The credential remains in chat history and any associated telemetry, exports, or backups. 2. The credential becomes part of the local skill source and can subsequently be copied, archived, shared, or committed to version control. Storing the key in source code violates secret-management best practices and is not necessary for the skill's declared operation. The runner already reads `Pixelhub_API_KEY` from the environment. A protected environment injection mechanism or credential store would provide the required authentication without modifying package files. No evidence indicates that the package contains a preinstalled real credential. The r ...[truncated 1167 chars]
Remediation
## Remediation Suggestions 1. Remove all instructions asking users to submit API keys through chat. 2. Remove the instruction to replace `DEFAULT_API_KEY` in the source file. 3. Require the existing `Pixelhub_API_KEY` environment variable or integrate an operating-system credential store or managed secret provider. 4. Keep `DEFAULT_API_KEY` as a non-secret sentinel and fail safely when no externally supplied credential is available. 5. Document secure, platform-specific secret injection without printing the key to the terminal or logs. 6. Add secret-scanning controls to development and release workflows. 7. Ensure local secret configuration files are excluded from source control. 8. Advise users who followed the old procedure to remove the embedded key, delete exposed copies where possible, and rotate the credential through the Pixelle account portal.

T09 · Insecure Skill Coding Practices

Error
Location
pixelhub_api_runner.py:35
Finding
API credentials can be forwarded to an arbitrary base URL## Vulnerability Details **File Location**: `pixelhub_api_runner.py:35-49` **Related Location**: `pixelhub_api_runner.py:276-284` **Vulnerability Type**: Unrestricted credential destination and missing transport validation **Risk Level**: High ### Vulnerable Code The request method unconditionally attaches the API key to the configured destination: ```python def _request(self, method: str, path: str, payload=None, retryable: bool = False): url = f"{self.base_url}{path}" headers = {"X-API-Key": self.api_key} data = None if payload is not None: headers["Content-Type"] = "application/json" data = json.dumps(payload).encode("utf-8") attempts = self.request_retries + 1 if retryable else 1 last_error = None for attempt in range(attempts): req = urllib.request.Request(url, data=data, headers=headers, method=method) try: with urllib.request.urlopen(req, timeout=self.timeout) as resp: ``` The destination can be controlled through either a command-line argument or an environment variable: ```python p.add_argument( "--base-url", default=os.getenv("Pixelhub_BASE_URL", DEFAULT_BASE_URL), help="Pixelhub base URL", ) p.add_argument( "--api-key", default=os.getenv("Pixelhub_API_KEY", DEFAULT_API_KEY), help="Pixelhub API key", ) ``` ### Technical Analysis Every API call sends `self.api_key` in the `X-API-Key` header to `self.base_url`. The base URL is accepted from `--base-url` or `Pixelhub_BASE_URL` without validating its scheme, hostname, port, or relationship to the declared Pixelle service. Consequently, an invocation can redirect authenticated requests to an attacker-controlled host. A non-HTTPS URL can also cause the credential and submitted content to travel without transport encryption. The default URL is the expected `https://www.pixellelabs.com`, so the network transfer is legitimate under n ...[truncated 1869 chars]
Remediation
## Remediation Suggestions 1. Restrict authenticated requests to the declared origin, `https://www.pixellelabs.com`. 2. Parse the base URL before creating requests and reject: - Schemes other than HTTPS. - Hostnames outside an explicit allowlist. - Embedded usernames or passwords. - Unexpected ports. - Fragments, query strings, or nonempty base paths unless specifically required. 3. Avoid exposing `--base-url` in production if the skill only supports one service. 4. If custom endpoints are genuinely required, do not forward the production API key by default. Require explicit confirmation and separate credentials scoped to the custom endpoint. 5. Revalidate the destination after redirects, or disable cross-origin redirects for authenticated requests, so an approved origin cannot redirect the credential to another host. 6. Add tests verifying that HTTP URLs, lookalike domains, subdomain tricks, user-info URLs, and cross-origin redirects are rejected. 7. Clearly notify users that prompts, media URLs, task names, and other supplied parameters are transmitted to the approved external service.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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 (7)

Ae1

High
Category
analysis-evasion
Content
- Required runner: `pixelhub_api_runner.py` (same folder as this `SKILL.md`)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Missing User Warnings

High
Confidence
98% confidence
Finding
The skill instructs the user to send an API key directly in chat, but provides no privacy warning, secure handling guidance, or safer alternative. Credentials pasted into chat may be logged, retained, exposed to downstream systems, or mishandled by the agent, making this a direct secret-handling risk.

Ssd 3

High
Confidence
99% confidence
Finding
The skill not only collects a user's API key in chat but also instructs the agent to persist that secret into a local runner file. This creates a durable credential exposure risk through source files, backups, logs, version control, or later unintended disclosure, and is especially dangerous because the skill is intended for repeated direct API use.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill declares executable behavior that uses environment access and outbound network access but does not constrain its scope with explicit permissions or allowed-tools metadata. This increases the chance of overbroad activation and unintended execution paths, especially because the skill is designed to handle user-supplied credentials and make live API calls.

Vague Triggers

Medium
Confidence
87% confidence
Finding
The activation description is very broad and can trigger the skill for a wide range of image, video, or audio requests without clear boundaries. In context, that matters because activation may lead the agent into credential collection and local file modification flows that should only occur with explicit user intent.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
This code sends the user's API key in the X-API-Key header on outbound network requests, but there is no user-facing warning, confirmation, or explanatory log around that transmission. For a code file, transmitting credentials or user/system data over the network should have some visible disclosure unless clearly documented elsewhere in the skill description, which is not present in this file.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The code constructs and returns user-visible balance labels in Chinese (for example, '像素币' and '当前余额') regardless of user preference or locale. This is a natural-language policy issue because it imposes a specific language without opt-in or any documented locale selection mechanism.

Static analysis

No suspicious patterns detected.