T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/notes-list.sh:29
- Finding
- AppleScript Injection Through Unvalidated Limit Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/notes-list.sh:8-12,21-29`; `scripts/notes-search.sh:10-20,93-102` **Vulnerability Type**: AppleScript source injection **Risk Level**: High ### Vulnerable Code ```bash # scripts/notes-list.sh FOLDER="${1:-}" LIMIT="${2:-20}" resolve_folder "$FOLDER" osascript <<EOF tell application "Notes" try $FOLDER_SCRIPT on error errMsg return "Error: " & errMsg end try set maxCount to $LIMIT as integer ``` ```bash # scripts/notes-search.sh for arg in "$@"; do case "$arg" in --title-only) TITLE_ONLY=true ;; --spotlight) SPOTLIGHT=true ;; *) if [ -z "$QUERY" ]; then QUERY="$arg" elif [ -z "$FOLDER" ]; then FOLDER="$arg" else LIMIT="$arg" fi ;; esac done osascript <<EOF tell application "Notes" try $FOLDER_SCRIPT on error errMsg return "Error: " & errMsg end try set searchTerm to "$ESCAPED_QUERY" as text set maxCount to $LIMIT as integer ``` ### Technical Analysis Both scripts insert the attacker-controlled `LIMIT` argument directly into an unquoted AppleScript heredoc. No numeric validation is performed before the value becomes part of executable AppleScript source. Shell quoting at the point where the command-line argument is received does not make this safe. Variable expansion still occurs while constructing the heredoc. An argument containing a newline, an AppleScript statement, and a comment marker can terminate the expected assignment and introduce additional statements. AppleScript's `do shell script` command can then be used to invoke local shell commands. ### Attack Path 1. An attacker causes the skill or a user to invoke `notes-list.sh` or `notes-search.sh` with a crafted limit argument. 2. The script stores the complete value in `LIMIT` without checking that it contains only decimal digits. 3. The heredoc expands `$LIMIT` directly into ...[truncated 862 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Validate the limit before invoking AppleScript: ```bash if ! [[ "$LIMIT" =~ ^[0-9]+$ ]] || (( LIMIT < 1 || LIMIT > 1000 )); then echo "Error: limit must be an integer between 1 and 1000" >&2 exit 1 fi ``` - Avoid generating AppleScript source from command-line values. Pass values through `osascript` arguments: ```bash osascript - "$LIMIT" <<'EOF' on run argv set maxCount to (item 1 of argv) as integer -- Remaining logic end run EOF ``` - Use a quoted heredoc delimiter so shell expansion cannot unexpectedly modify the AppleScript source. - Apply the same validation and argument-passing pattern in both `notes-list.sh` and `notes-search.sh`. ]]>
