T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/download_kaggle.sh:29
- Finding
- Wildcard Archive Handling Can Delete or Overwrite Unrelated Files## Vulnerability Details **File Location**: `scripts/download_kaggle.sh`, lines 29-35 **Vulnerability Type**: Unsafe wildcard extraction and deletion **Risk Level**: Medium **Vulnerable Code**: ```bash # Unzip if downloaded successfully if [ $? -eq 0 ]; then echo "Download successful. Extracting..." cd "$OUTPUT_DIR" unzip -q *.zip rm *.zip echo "Dataset ready in: $OUTPUT_DIR" ``` ### Technical Analysis The script uses the `*.zip` wildcard for both archive extraction and deletion. Consequently, it does not restrict these operations to the archive downloaded by the current Kaggle command. If the output directory contains multiple ZIP files, shell expansion passes all matching names to `unzip`. The `unzip` utility does not reliably interpret multiple positional ZIP names as independent archives; additional names may instead be treated as archive member patterns. More importantly, the subsequent `rm *.zip` command deletes every matching archive regardless of whether each archive was downloaded by this execution or successfully extracted. Archive contents are also extracted directly into the selected output directory without checking entry paths, detecting collisions, or preventing replacement of existing files. The exact overwrite and path traversal behavior depends on the installed `unzip` implementation, but the script itself provides no protective validation. ### Attack Path 1. A user selects an output directory that already contains one or more unrelated ZIP archives. 2. Alternatively, another local process or user with write access places an archive in that directory before extraction. 3. The Kaggle download completes successfully, causing the script to enter the extraction branch. 4. `unzip -q *.zip` operates on the wildcard expansion rather than a specifically identified downloaded file. 5. Extraction may overwrite files in the output directory, depending on archive contents and `unzip` ...[truncated 1003 chars]
- Remediation
- ## Remediation Suggestions - Create a unique temporary directory for every download using `mktemp -d`. - Capture or deterministically construct the exact downloaded archive path. - Never use `*.zip` for destructive operations. - List and validate archive entries before extraction. Reject absolute paths, parent-directory traversal components, symbolic links, and other unsafe entries. - Extract into a newly created destination directory with no-overwrite behavior where supported. - Delete only the exact archive created by the current operation. - Delete the archive only after extraction and validation have completed successfully. - Check the results of `cd`, `unzip`, and `rm`, or enable strict shell behavior with appropriate error handling. Example hardening pattern: ```bash set -euo pipefail mkdir -p -- "$OUTPUT_DIR" OUTPUT_DIR="$(cd -- "$OUTPUT_DIR" && pwd)" WORK_DIR="$(mktemp -d "$OUTPUT_DIR/.kaggle-download.XXXXXX")" trap 'rm -rf -- "$WORK_DIR"' EXIT kaggle datasets download -d "$DATASET_NAME" -p "$WORK_DIR" mapfile -d '' archives < <(find "$WORK_DIR" -maxdepth 1 -type f -name '*.zip' -print0) if [ "${#archives[@]}" -ne 1 ]; then echo "Expected exactly one downloaded ZIP archive" >&2 exit 1 fi archive="${archives[0]}" if unzip -Z1 "$archive" | grep -Eq '(^/|(^|/)\.\.(/|$))'; then echo "Archive contains unsafe paths" >&2 exit 1 fi unzip -q -n -- "$archive" -d "$OUTPUT_DIR" rm -- "$archive" ```
