T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/checklist.sh:416
- Finding
- Path Traversal in Checklist Template Selection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/checklist.sh:416-423` **Vulnerability Type**: Path traversal and unauthorized local file selection **Risk Level**: Medium ### Vulnerable Code ```bash local template_file="${TEMPLATES_DIR}/${name}.json" if [[ -f "$template_file" ]]; then cp "$template_file" "${ACTIVE_DIR}/current.json" # Reset all statuses local temp=$(mktemp) jq '.items[] |= {"id": .id, "text": .text, "status": "pending", "required": .required, "assigned_to": null, "completed_by": null, "depends_on": (.depends_on // [])}' \ "${ACTIVE_DIR}/current.json" > "$temp" && mv "$temp" "${ACTIVE_DIR}/current.json" ``` ### Technical Analysis The template name is supplied through the command-line interface and concatenated directly into a filesystem path: ```bash "${TEMPLATES_DIR}/${name}.json" ``` The implementation does not reject path separators, `..` components, absolute-path constructs, or other characters outside the expected template-name format. The `[[ -f "$template_file" ]]` test only confirms that the resolved path is a regular file; it does not confirm that the file remains inside `TEMPLATES_DIR`. Consequently, a crafted template name can escape `~/.checklist/templates` and select another user-readable file whose name ends in `.json`. The selected file is copied into `~/.checklist/active/current.json` before its structure is processed by `jq`. No privilege escalation is involved: access remains limited to files readable by the operating-system account running the script. ### Attack Path 1. An attacker who can invoke the CLI creates a readable JSON file outside the template directory, or identifies an existing one. 2. The attacker supplies a traversal sequence as the template name, for example: ```bash checklist create ../../../../tmp/target ``` 3. The application constructs a path similar to: ```text ~/.checklist/templates/../../../../tmp/target.json ``` 4. The regular-file ch ...[truncated 898 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Restrict template names to a conservative identifier format: ```bash if [[ ! "$name" =~ ^[A-Za-z0-9_-]+$ ]]; then print_error "Invalid template name" return 1 fi ``` 2. Canonicalize both the template directory and candidate path, then verify that the candidate remains below the trusted directory: ```bash template_root=$(realpath "$TEMPLATES_DIR") template_file=$(realpath -m "${TEMPLATES_DIR}/${name}.json") if [[ "$template_file" != "$template_root/"* ]]; then print_error "Template path escapes the template directory" return 1 fi ``` 3. Validate the JSON schema before replacing active state. At minimum, require an object containing an `items` array with appropriately typed fields. 4. Process the selected file into a temporary file first, and move it into place only after every validation and transformation succeeds. Do not copy unvalidated content directly over `current.json`. 5. Add regression tests for names containing `../`, `/`, backslashes, absolute paths, embedded null-like input, and symbolic-link edge cases. ]]>
