T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/knowfun-cli.sh:55
- Finding
- Unescaped User Input Allows JSON Request Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/knowfun-cli.sh`, lines 55-98 **Vulnerability Type**: Unescaped user input in a manually constructed JSON request **Risk Level**: Medium ### Vulnerable Code ```bash cmd_create() { local task_type="$1" shift local material="$*" if [ -z "$task_type" ] || [ -z "$material" ]; then print_error "Usage: knowfun-cli.sh create <course|poster|game|film> <text or url>" exit 1 fi # Generate unique request ID local request_id="req_$(date +%s)_$(uuidgen | head -c 8)" # Determine if material is URL or text local material_type="text" local material_field="text" if [[ "$material" =~ ^https?:// ]]; then material_type="url" material_field="url" fi print_info "Creating $task_type task..." print_info "Request ID: $request_id" local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/api/openapi/v1/tasks" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"requestId\": \"$request_id\", \"taskType\": \"$task_type\", \"material\": { \"$material_field\": \"$material\", \"type\": \"$material_type\" } }") ``` ### Technical Analysis The `task_type` and `material` values originate from command-line arguments and are inserted directly into a JSON document. They are not encoded with a JSON serializer or escaped for use inside JSON strings. Shell quoting prevents these values from becoming separate shell commands, so this is not direct shell-command injection. However, shell quoting does not make the expanded values safe JSON. An input containing double quotes, backslashes, control characters, or JSON delimiters can terminate the intended string and alter the structure of the request body. For example, a crafted material value could close the `text` property and attempt to introduc ...[truncated 1906 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Construct request bodies using a JSON serializer rather than string interpolation. For example: ```bash case "$task_type" in course|poster|game|film) ;; *) print_error "Unsupported task type" exit 1 ;; esac if [ "${#material}" -gt 2048 ]; then print_error "Content exceeds the 2048-character limit" exit 1 fi payload=$(jq -n \ --arg requestId "$request_id" \ --arg taskType "$task_type" \ --arg field "$material_field" \ --arg material "$material" \ --arg materialType "$material_type" \ '{ requestId: $requestId, taskType: $taskType, material: { ($field): $material, type: $materialType } }') response=$(curl --fail-with-body --silent --show-error \ -w "\n%{http_code}" \ -X POST "$BASE_URL/api/openapi/v1/tasks" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ --data-binary "$payload") ``` 2. Validate `task_type` against the exact supported allowlist: `course`, `poster`, `game`, and `film`. 3. Enforce the documented content-length restriction before sending the request. 4. Reject control characters where they are not needed. 5. Add tests covering quotes, backslashes, newlines, Unicode, JSON delimiters, and oversized input. 6. Ensure the remote API also rejects unknown fields and performs strict schema validation; client-side validation must not be the only control. ]]>
