T09 · Insecure Skill Coding Practices
Warning
- Location
- random-sticker.sh:18
- Finding
- jq Expression Injection Through User-Controlled Sticker Tags<![CDATA[ ## Vulnerability Details **File Location**: `random-sticker.sh`, lines 18-31 **Vulnerability Type**: jq expression injection **Risk Level**: Medium ### Vulnerable Code ```bash # Build jq filter for multiple tags (OR logic) TAGS=("$@") JQ_FILTER='.collected[] | select(' for i in "${!TAGS[@]}"; do if [ $i -gt 0 ]; then JQ_FILTER+=" or " fi JQ_FILTER+=".tags[]? | contains(\"${TAGS[$i]}\")" done JQ_FILTER+=') | .file_id' # Get all matching stickers and pick random one cat "$STICKERS_JSON" | jq -r "$JQ_FILTER" | sort -R | head -1 ``` ### Technical Analysis Command-line tag values are concatenated directly into jq program source. The script does not encode these values or pass them as data through jq's `--arg` or `--args` interfaces. An attacker can supply quotation marks, jq operators, parentheses, and the jq comment character to terminate the intended `contains()` expression and append a different filter. This is jq-code injection rather than direct shell-command injection: the injected expression executes inside jq and can access any data loaded from `stickers.json`. For example, an argument shaped like: ```text ")) | . # ``` alters the generated jq expression so that complete matching sticker objects can be emitted rather than only their `file_id` fields. ### Attack Path 1. An attacker controls or influences a tag passed to `random-sticker.sh`, either through direct invocation or agent-controlled input. 2. The attacker supplies a crafted value containing jq syntax. 3. The script inserts that value into `JQ_FILTER` without data-safe parameterization. 4. jq evaluates the attacker-modified filter against the complete contents of `stickers.json`. 5. The altered filter may expose additional fields, disrupt sticker selection, generate errors, or consume excessive processing resources. ### Impact Assessment The attacker can manipulate query behavior over the complete local sticker collection. This can disclose sticker metada ...[truncated 388 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Do not construct jq source code from user input. Pass requested tags as data using `--args`, `--arg`, or `--argjson`. A safer implementation is: ```bash jq -r --args "$@" ' $ARGS.positional as $wanted | .collected[] | select(any(.tags[]?; . as $tag | any($wanted[]; $tag == .))) | .file_id ' "$STICKERS_JSON" | shuf -n 1 ``` Additional hardening should include: 1. Prefer exact tag equality instead of substring matching unless substring behavior is explicitly required. 2. Reject empty tags and enforce a reasonable maximum tag length and argument count. 3. Invoke jq with a fixed, static filter whose structure cannot be changed by input. 4. Add regression tests containing quotes, parentheses, pipes, backslashes, and jq comment characters. 5. Remove the unnecessary `cat` pipeline and pass the file directly to jq. ]]>
