T09 · Insecure Skill Coding Practices
Warning
- Location
- SKILL.md:240
- Finding
- Unsafe Shell and JSON Construction with User-Controlled Image Parameters<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 127-135, 150-153, and 240-253 **Vulnerability Type**: Command injection and malformed JSON caused by unsafe handling of user-controlled data **Risk Level**: Medium ### Vulnerable Code ```text If yes, collect URLs (comma-separated, max 14). For each URL, infer mimeType from suffix and build: ```json { "fileData": { "fileUri": "<url>", "mimeType": "<inferred>" } } ``` ``` ```text 1. **Build request**: Construct JSON with provider, model, prompt, imageConfig, and optional referenceImages 2. **Submit**: `POST https://api.labnana.com/openapi/v1/images/generation` with timeout of 600s ``` ```bash RESPONSE=$(curl -sS -X POST "https://api.labnana.com/openapi/v1/images/generation" \ -H "Authorization: Bearer $LISTENHUB_API_KEY" \ -H "Content-Type: application/json" \ --max-time 600 \ -d '{ "provider": "google", "model": "gemini-3-pro-image-preview", "prompt": "cyberpunk city at night", "imageConfig": {"imageSize": "2K", "aspectRatio": "16:9"} }') BASE64_DATA=$(echo "$RESPONSE" | jq -r '.candidates[0].content.parts[0].inlineData.data // .data') ``` ### Technical Analysis The skill directs the agent to place a user-supplied prompt and user-supplied reference-image URLs into a JSON request submitted through a shell command. However, it does not prescribe JSON-safe serialization or shell-safe argument handling. The example passes the JSON body as a single-quoted shell string. If an implementation replaces the fixed example prompt with user-controlled content through textual interpolation, an apostrophe can terminate the shell string. Additional shell syntax could then be interpreted as commands. Quotes, backslashes, control characters, and newlines can also corrupt the JSON even when they do not result in command execution. Reference-image URLs create the same class of risk if they are concatenated directly into the request body. Merely checking a URL suffix to infer a ...[truncated 1865 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Construct the request body using `jq` so every untrusted value is JSON-escaped: ```bash REQUEST_FILE=$(mktemp) trap 'rm -f "$REQUEST_FILE"' EXIT jq -n \ --arg provider "google" \ --arg model "$MODEL" \ --arg prompt "$PROMPT" \ --arg imageSize "$IMAGE_SIZE" \ --arg aspectRatio "$ASPECT_RATIO" \ '{ provider: $provider, model: $model, prompt: $prompt, imageConfig: { imageSize: $imageSize, aspectRatio: $aspectRatio } }' > "$REQUEST_FILE" curl -sS -X POST \ "https://api.labnana.com/openapi/v1/images/generation" \ -H "Authorization: Bearer $LISTENHUB_API_KEY" \ -H "Content-Type: application/json" \ --max-time 600 \ --data-binary "@$REQUEST_FILE" ``` 2. Build reference-image arrays with `jq --arg` or `jq --argjson`; never concatenate URLs into a JSON or shell string. 3. Treat model, resolution, and aspect-ratio selections as allowlisted enumerations rather than arbitrary strings. 4. Validate reference URLs with a proper URL parser. Permit only intended schemes such as `https`, reject embedded credentials, and enforce the maximum count separately. 5. Avoid `eval`, generated shell source, and nested command strings for all user-controlled values. 6. Check `curl` exit status and HTTP status before processing the response. Verify that extracted base64 data exists and is valid before decoding it. ]]>
