T09 · Insecure Skill Coding Practices
Note
- Location
- scripts/inbox.sh:178
- Finding
- Predictable Temporary File Enables Symlink Overwrite and Concurrent Data Corruption## Vulnerability Details **File Location**: `scripts/inbox.sh:178`, `scripts/inbox.sh:296`, and `scripts/inbox.sh:317` **Vulnerability Type**: Predictable temporary file, symlink following, and missing update locking **Risk Level**: Low ### Vulnerable Code ```bash # scripts/inbox.sh:178 ' "$DB" > "$DB.tmp" && mv "$DB.tmp" "$DB" # scripts/inbox.sh:296 ' "$DB" > "$DB.tmp" && mv "$DB.tmp" "$DB" # scripts/inbox.sh:317 jq --argjson id "$id" '.items |= map(select(.id != $id))' "$DB" > "$DB.tmp" && mv "$DB.tmp" "$DB" ``` The same fixed temporary path, `data/items.json.tmp`, is used by the `add`, `status`, and `delete` operations. ### Technical Analysis Shell redirection opens the predictable `"$DB.tmp"` path before `jq` runs. The script does not create the temporary file exclusively, verify that it is a regular file, reject symbolic links, or hold a lock over the read-modify-write transaction. A local process with write access to the Skill's data directory can pre-create `items.json.tmp` as a symbolic link. The redirection may then follow that link and overwrite a target file writable by the account running the Skill. Concurrent legitimate invocations also share the same temporary file and read the database independently. Their writes can interfere with one another, producing lost updates, failed moves, or corrupted archive state. ### Attack Path 1. An attacker obtains local write access to the project's `data` directory. 2. The attacker creates the predictable path as a symbolic link: ```bash ln -s /path/to/user-writable-target data/items.json.tmp ``` 3. The victim invokes an operation that modifies the database: ```bash bash scripts/inbox.sh add --type note --title "Example" --content "Example" ``` 4. Shell redirection follows the symbolic link and writes generated JSON to the linked target. 5. The subsequent `mv` may fail or alter database state, depending on the filesystem and path state. Alternatively, two simultaneous `add`, `status ...[truncated 665 chars]
- Remediation
- ## Remediation Suggestions - Create a unique temporary file in the database directory using `mktemp`: ```bash tmp_file="$(mktemp "$BASE_DIR/data/.items.json.XXXXXX")" ``` - Register a cleanup trap immediately: ```bash trap 'rm -f -- "$tmp_file"' EXIT ``` - Serialize the complete read-modify-write transaction with `flock` or an equivalent locking mechanism. - Write the transformed JSON to the unique file, verify it with `jq -e`, set restrictive permissions, and atomically rename it over the database: ```bash jq '...' "$DB" > "$tmp_file" jq -e . "$tmp_file" >/dev/null chmod 600 "$tmp_file" mv -f -- "$tmp_file" "$DB" trap - EXIT ``` - Ensure the `data` directory is not writable by untrusted users and has restrictive ownership and permissions. - Apply the same safe update helper consistently to the `add`, `status`, and `delete` operations.
