T09 · Insecure Skill Coding Practices
- Location
scripts/zhipu_search.sh:10- Finding
JSON Injection Through Unvalidated Command-Line Parameters
- Content
View full analysis
[--engine ] [--count ] [--intent] [--recency ]" exit 0 ;; *) echo "Unknown parameter: $1"; exit 1 ;; esac shift done # Escape quotes and backslashes in the query for safe JSON encoding SAFE_QUERY="${QUERY//\\/\\\\}" SAFE_QUERY="${SAFE_QUERY//\"/\\\"}" # Build JSON payload manually PAYLOAD="{\"search_query\": \"$SAFE_QUERY\", \"search_engine\": \"$ENGINE\", \"search_intent\": $INTENT, \"count\": $COUNT, \"search_recency_filter\": \"$RECENCY\"}" ``` ### Technical Analysis The script constructs an API request by directly concatenating command-line parameters into a JSON string. Although backslashes and double quotes are escaped in `QUERY`, the following parameters receive no equivalent JSON encoding or semantic validation: - `ENGINE`, inserted inside a JSON string - `RECENCY`, inserted inside a JSON string - `COUNT`, inserted directly as a raw JSON value The script does not enforce the documented allowlists for the engine and recency options, nor does it verify that `COUNT` is an integer between 1 and 50. An attacker who can influence the script arguments can therefore insert JSON syntax into these fields. Depending on the supplied value, this can add arbitrary properties, create duplicate properties, alter request semantics, or make the payload invalid. The query-specific escaping is also incomplete as a general JSON encoder because it does not enco ...[truncated 2159 chars]- Remediation
View remediation
&2 exit 1 ;; esac ``` 3. Enforce an explicit allowlist for `RECENCY`: ```bash case "$RECENCY" in oneDay|oneWeek|oneMonth|oneYear|noLimit) ;; *) echo "Error: invalid recency filter" >&2 exit 1 ;; esac ``` 4. Require `COUNT` to contain only digits and enforce the documented range: ```bash if ! [[ "$COUNT" =~ ^[0-9]+$ ]] || (( COUNT < 1 || COUNT > 50 )); then echo "Error: count must be an integer from 1 to 50" >&2 exit 1 fi ``` 5. Check that every option requiring a value has a following argument before reading `$2`. 6. Build the payload using a serializer, for example: ```bash PAYLOAD="$(jq -n \ --arg query "$QUERY" \ --arg engine "$ENGINE" \ --argjson intent "$INTENT" \ --argjson count "$COUNT" \ --arg recency "$RECENCY" \ '{ search_query: $query, search_engine: $engine, search_intent: $intent, count: $count, search_recency_filter: $recency }')" ``` A serializer ensures that quotes, backslashes, control characters, and Unicode content are represented safely and prevents user input from changing the JSON structure. ]]>
