T09 · Insecure Skill Coding Practices
- Location
scripts/readwise.sh:158- Finding
Command Injection Through the Unvalidated list --limit Argument
- Content
View full analysis
100 ? 100 : remaining)) local params="limit=${page_size}" # ... local count count=$(echo "$all_results" | jq 'length') remaining=$((limit - count)) done ``` ### Technical Analysis The `cmd_list` function accepts an arbitrary string through `--limit` and stores it in `limit`. The same value is copied into `remaining`, after which both variables are evaluated as Bash arithmetic expressions. Bash arithmetic evaluation is not equivalent to strict integer parsing. Variable contents can be recursively interpreted as arithmetic syntax. In particular, malicious expressions involving array subscripts can trigger command substitutions while Bash resolves the expression. Consequently, quoting the original command-line argument does not make its later use in `$((...))` safe. This vulnerability is reachable before the value is established to be a decimal integer. It therefore creates a local command-execution primitive when an attacker can influence arguments passed to the Skill. ### Attack Path 1. An attacker causes the agent or user to invoke `readwise.sh list` with a crafted `--limit` value instead of an integer. 2. Argument parsing stores the complete attacker-controlled expression in `limit`. 3. The value is copied to `remaining`. 4. Pagination evaluates `remaining` in `local page_size=$((...))`, and later evaluates `limit` in `remaining=$((limit - count))`. 5. Bash interprets the supplied content as arithmetic syntax. A crafted expression using arithmetic array-index evaluation can cause an embedded command substitution to run. 6. The ...[truncated 719 chars]- Remediation
View remediation
0 )) || die "--limit must be greater than zero" ``` Additional hardening should include: 1. Enforce a reasonable maximum value to prevent excessive API calls or memory consumption. 2. Convert the validated value once and use only the normalized integer afterward. 3. Apply the same validation consistently to every numeric command-line option. 4. Add regression tests covering empty, negative, hexadecimal-like, arithmetic-expression, array-subscript, and excessively large values. 5. Reject missing option values explicitly before reading `$2`, producing a controlled validation error. ]]>
