Back to skill

Security audit

Qwen Image Plus Sophnet

Security checks for vulnerabilities and agentic risk

Overview

This image-generation skill largely does what it says, but its shell script has a real input-validation flaw that can allow local command execution through a timing option.

Review before installing. Use only with trusted prompts and options, prefer SOPHNET_API_KEY over --api-key, use a scoped Sophnet token, and require the publisher to validate numeric options such as --max-wait and --poll-interval before use.

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
scripts/generate_image.sh:97
Finding
Arithmetic Expression Injection Through Unvalidated --max-wait Argument<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_image.sh`, lines 97-100 and 204-210 **Vulnerability Type**: Shell arithmetic expression injection **Risk Level**: High ### Vulnerable Code ```bash --max-wait) MAX_WAIT="$2" shift 2 ;; ``` The unvalidated value is subsequently used in a Bash arithmetic expression: ```bash now_ts="$(date +%s)" elapsed="$((now_ts - start_ts))" if (( elapsed > MAX_WAIT )); then echo "Error: timed out after ${MAX_WAIT}s." >&2 exit 1 fi ``` ### Technical Analysis The `--max-wait` value is copied directly into `MAX_WAIT` without confirming that it is a decimal integer. Bash recursively interprets variable values used in arithmetic contexts as arithmetic expressions rather than treating them strictly as numeric data. An attacker who can influence the script arguments can therefore provide a crafted arithmetic expression. Bash arithmetic expressions support constructs such as array subscripts, and command substitutions embedded in such constructs may be evaluated by the shell. Consequently, evaluation of the condition: ```bash (( elapsed > MAX_WAIT )) ``` can cause attacker-controlled shell commands to execute. The nearby `--poll-interval` argument is also not validated. It is passed to `sleep`, which can permit malformed values or excessively long delays, although it is not directly used in a Bash arithmetic expression. ### Attack Path 1. An attacker gains the ability to control or influence arguments passed to `generate_image.sh`. 2. The attacker supplies a crafted arithmetic expression through `--max-wait`. 3. The script accepts the value without numeric validation. 4. After creating an image task, the polling loop reaches the arithmetic comparison at line 207. 5. Bash recursively evaluates the attacker-controlled value as an arithmetic expression. 6. Any command substitution embedded in an evaluated arithmetic construct runs with the privileges and environment of the Skill process. ### Imp ...[truncated 572 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Validate `MAX_WAIT` before it enters any arithmetic context. Require a bounded, non-negative decimal integer: ```bash if [[ ! "$MAX_WAIT" =~ ^[0-9]+$ ]]; then echo "Error: invalid --max-wait (must be a non-negative integer)." >&2 exit 1 fi if (( 10#$MAX_WAIT > 3600 )); then echo "Error: --max-wait must not exceed 3600 seconds." >&2 exit 1 fi ``` The `10#` prefix forces decimal interpretation after validation and avoids unintended octal handling of values with leading zeroes. Apply similar validation and reasonable bounds to `POLL_INTERVAL`: ```bash if [[ ! "$POLL_INTERVAL" =~ ^[0-9]+([.][0-9]+)?$ ]]; then echo "Error: invalid --poll-interval." >&2 exit 1 fi ``` For stronger hardening: - Reject missing option values before accessing `$2`. - Enforce minimum and maximum values for all numeric parameters. - Validate `N` against the API's documented range rather than checking only that it contains digits. - Keep attacker-controlled strings out of shell arithmetic expressions whenever possible. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_image.sh:190
Finding
Sophnet API Token Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_image.sh`, lines 89-92, 190-194, and 220-223 **Vulnerability Type**: Sensitive credential exposure through process arguments and shell history **Risk Level**: Medium ### Vulnerable Code The script permits the API token to be supplied directly as a command-line argument: ```bash --api-key) API_KEY="$2" shift 2 ;; ``` It then expands the token into curl's argument vector when creating the task: ```bash create_resp="$(curl -sS -X POST "https://www.sophnet.com/api/open-apis/projects/easyllms/imagegenerator/task" \ -H "Authorization: Bearer ${API_KEY}" \ -H "Content-Type: application/json" \ -d "${payload}" )" ``` The same exposure occurs during every polling request: ```bash status_resp="$(curl -sS -X GET "https://www.sophnet.com/api/open-apis/projects/easyllms/imagegenerator/task/${task_id}" \ -H "Authorization: Bearer ${API_KEY}" )" ``` ### Technical Analysis Supplying the token through `--api-key` can record it in interactive shell history, process execution logs, diagnostic output, or orchestration metadata. Even when the token originates from `SOPHNET_API_KEY`, the script interpolates it into curl's `-H` argument. This places the complete bearer token in curl's process argument vector. Depending on operating-system process visibility controls, monitoring configuration, and user permissions, another local process may be able to inspect that argument while curl is running. Polling repeats the exposure for each status request, increasing the observation window. ### Attack Path 1. A user starts the Skill with `--api-key`, or the script reads the token from `SOPHNET_API_KEY`. 2. The script expands the token into the `Authorization` header supplied as a curl command-line argument. 3. A local attacker or monitoring component with sufficient process-inspection access observes curl's argument vector while a request is active. If `--api-key` was used, the token may also be ...[truncated 782 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Remove or deprecate the `--api-key` option so credentials are not entered directly on the command line. Prefer a protected environment variable, secret manager, or restricted credential file. Avoid placing the token in curl's argument vector. One option is to provide sensitive curl configuration through standard input: ```bash create_resp="$( printf 'header = "Authorization: Bearer %s"\n' "$API_KEY" | curl -sS --config - \ -X POST \ -H "Content-Type: application/json" \ -d "$payload" \ "https://www.sophnet.com/api/open-apis/projects/easyllms/imagegenerator/task" )" ``` Additional hardening measures include: - Use a dedicated API token with only the permissions required for image generation. - Prevent command tracing around secret-handling code and ensure `set -x` is never enabled. - Do not print API responses if they may contain credentials or sensitive account information. - If a temporary credential file is necessary, create it with mode `0600`, store it in a protected directory, and remove it reliably with a `trap`. - Rotate any token suspected of having appeared in shell history, process logs, or monitoring data. - Configure operating-system process visibility restrictions where applicable. ]]>
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)

Lp3

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding
The skill instructs the agent to execute a local shell script using a user-controlled prompt, but the manifest does not declare any tool scope or allowed shell capability. This creates an authorization and transparency gap: a reviewer or runtime may not realize the skill can invoke shell commands and reach external APIs, increasing the risk of unintended code execution or misuse if the script or its inputs are unsafe.

External Transmission

Medium
Category
Data Exfiltration
Content
fi
payload="${payload}}"

create_resp="$(curl -sS -X POST "https://www.sophnet.com/api/open-apis/projects/easyllms/imagegenerator/task" \
  -H "Authorization: Bearer ${API_KEY}" \
  -H "Content-Type: application/json" \
  -d "${payload}"
Confidence
70% 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

Medium
Confidence
89% confidence
Finding
This shell script makes a POST request to an external API and includes user-supplied prompt data plus a bearer token, but there is no explicit disclosure in comments, help text, or runtime output that the prompt will be sent to a remote service. Under the code-file criteria, network calls that transmit user or system data should have some visible warning unless the disclosure is already clearly provided.

Static analysis

No suspicious patterns detected.