T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/task-system.sh:13
- Finding
- SQL Injection Through Unvalidated Task Identifiers<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/task-system.sh:13-21` - `scripts/heartbeat.sh:5-10` - `scripts/complete-task.sh:5-16` **Vulnerability Type**: SQL injection through direct interpolation of untrusted command-line input **Risk Level**: High ### Vulnerable Code `scripts/task-system.sh:13-21`: ```bash heartbeat|update) TASK_ID="${2:-1}" sqlite3 "$DB_PATH" "UPDATE tasks SET last_updated=CURRENT_TIMESTAMP WHERE id=$TASK_ID;" echo "Task #$TASK_ID heartbeat updated" ;; complete|done) TASK_ID="${2:-1}" NOTES="${3:-}" sqlite3 "$DB_PATH" "UPDATE tasks SET status='completed', completed_at=CURRENT_TIMESTAMP, last_updated=CURRENT_TIMESTAMP, notes='$(echo \"$NOTES\" | sed "s/'/''/g")' WHERE id=$TASK_ID;" ``` `scripts/heartbeat.sh:5-10`: ```bash DB_PATH="${HOME}/.openclaw/workspace/databases/tasks.db" TASK_ID="${1:-1}" [ -f "$DB_PATH" ] || exit 1 sqlite3 "$DB_PATH" "UPDATE tasks SET last_updated=CURRENT_TIMESTAMP WHERE id=$TASK_ID;" ``` `scripts/complete-task.sh:5-16`: ```bash DB_PATH="${HOME}/.openclaw/workspace/databases/tasks.db" TASK_ID="${1:-1}" NOTES="${2:-}" [ -f "$DB_PATH" ] || exit 1 sqlite3 "$DB_PATH" "UPDATE tasks SET status='completed', completed_at=CURRENT_TIMESTAMP, last_updated=CURRENT_TIMESTAMP, notes='$(echo "$NOTES" | sed "s/'/''/g")' WHERE id=$TASK_ID;" ``` ### Technical Analysis The scripts obtain `TASK_ID` directly from a command-line argument and interpolate it into SQL without verifying that it is an integer. Shell quoting does not prevent SQL injection because the untrusted value becomes part of the SQL statement passed to the SQLite command-line client. The SQLite client accepts multiple SQL statements in one input string. Consequently, a value containing a statement terminator can modify the intended query and append additional SQL. Escaping performed for `NOTES` does not protect `TASK_ID`. For example, a task ID conceptually shaped like the following changes the q ...[truncated 1275 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Strictly validate every task identifier before constructing a query: ```bash TASK_ID="${2:-}" if [[ ! "$TASK_ID" =~ ^[0-9]+$ ]]; then echo "Error: task ID must be a positive integer" >&2 exit 2 fi ``` 2. Apply equivalent validation in `task-system.sh`, `heartbeat.sh`, and `complete-task.sh`. 3. Do not silently default mutation operations to task ID `1`; require an explicit identifier to reduce accidental changes. 4. Prefer a SQLite API that supports bound parameters rather than constructing SQL with shell interpolation. 5. Check the SQLite process exit status and verify that exactly one expected row was affected before printing a success message. 6. Add regression tests using malformed values such as spaces, negative values, quotes, semicolons, SQL comments, and multiple statements. ]]>
