T09 · Insecure Skill Coding Practices
- Location
scripts/lyrion.sh:56- Finding
Unescaped User Input Enables JSON-RPC Request Injection
- Content
View full analysis
Vulnerability Details
File Location:
scripts/lyrion.sh, lines 56-68
Vulnerability Type: JSON injection through unsafe request construction
Risk Level: MediumVulnerable Code
bash send_request() { local player_id="$1" shift # Parameter als JSON-Array aufbauen local params="" for param in "$@"; do if [ -z "$params" ]; then params="\"$param\"" else params="$params, \"$param\"" fi done local json="{\"id\":1,\"method\":\"slim.request\",\"params\":[\"$player_id\",[$params]]}" curl -s -X POST \ -H "Content-Type: application/json" \ -d "$json" \ "$URL" }Technical Analysis
The function manually constructs a JSON document by interpolating
player_idand command parameters directly into quoted JSON strings. It does not escape quotation marks, backslashes, control characters, or other JSON-significant input.Several commands pass caller-controlled values to this function, including player IDs, search terms, artist and album IDs, and playlist URIs. A crafted argument can therefore terminate its intended JSON string and alter the surrounding JSON structure. Depending on what the Lyrion Music Server parser accepts, this can produce malformed requests or inject modified RPC parameters and unintended operations.
Shell metacharacters inside these values are not evaluated as local shell commands because the variables are expanded inside quoted shell arguments. The confirmed weakness is JSON-RPC request injection, not local shell-command injection.
Attack Path
- An attacker obtains influence over arguments supplied to commands such as
add,insert,playuri,search, orstatus. - The attacker supplies a value containing JSON control characters, such as an unescaped quotation mark followed by crafted JSON structure.
send_requestconcatena ...[truncated 1178 chars]
- An attacker obtains influence over arguments supplied to commands such as
- Remediation
View remediation
Remediation Suggestions
Replace manual JSON concatenation with a JSON-aware serializer. Every player ID and parameter must be supplied as data rather than inserted into JSON syntax.
A robust implementation can use Python's
jsonmodule:bash send_request() { local player_id="$1" shift local json json="$( python3 - "$player_id" "$@" <<'PY' import json import sys player_id = sys.argv[1] command_parameters = sys.argv[2:] print(json.dumps({ "id": 1, "method": "slim.request", "params": [player_id, command_parameters], })) PY )" || return 1 curl --silent --show-error --fail \ --request POST \ --header "Content-Type: application/json" \ --data-binary "$json" \ "$URL" }Alternatively, use
jq -nwith--argand--argsso that it performs all escaping. Do not attempt to secure the current concatenation using ad hoc character replacement.Additional hardening should include:
- Validate player IDs against the expected identifier format.
- Enforce numeric ranges and formats for volume, index, artist ID, and album ID arguments.
- Restrict URI schemes to those explicitly required by the Skill.
- Add tests for quotation marks, backslashes, newlines, control characters, Unicode, and JSON-shaped arguments.
- Use
curl --fail --show-errorand propagate failures rather than silently accepting server or transport errors. - Keep the plaintext HTTP API on a trusted network, or place it behind an authenticated TLS reverse proxy when requests cross an untrusted network.
