T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/add_note.sh:13
- Finding
- Insufficient Path Validation Allows Arbitrary User-Scoped File Modification and Unsafe NextCloud Copies## Vulnerability Details **File Location**: `scripts/add_note.sh:13-45`, `scripts/add_note.sh:54-55`, `scripts/add_note.sh:135-159`, and `scripts/add_note.sh:165-179` **Vulnerability Type**: Improper path validation and arbitrary file write **Risk Level**: High ### Vulnerable Code ```bash validate_safe_path() { local path="$1" local purpose="$2" # Convert to absolute path local abs_path=$(realpath -m "$path" 2>/dev/null || echo "$path") # Security checks if [[ "$abs_path" =~ ^/etc/ ]]; then echo "❌ Security error: Cannot write to system directory /etc/" >&2 exit 1 fi if [[ "$abs_path" =~ ^/usr/ ]]; then echo "❌ Security error: Cannot write to system directory /usr/" >&2 exit 1 fi if [[ "$abs_path" =~ ^/bin/|^/sbin/|^/lib/|^/lib64/ ]]; then echo "❌ Security error: Cannot write to system binaries directory" >&2 exit 1 fi # Ensure it's within user's home or current directory local user_home="${HOME:-/tmp}" if [[ ! "$abs_path" =~ ^$user_home ]] && [[ ! "$abs_path" =~ ^$(pwd) ]]; then echo "⚠️ Warning: $purpose path is outside user directory: $abs_path" >&2 echo " Only writing to user home or current directory is allowed for safety." >&2 exit 1 fi # Ensure it's a .md file for diary if [[ "$purpose" == "diary" ]] && [[ ! "$abs_path" =~ \.md$ ]]; then echo "⚠️ Warning: Diary file should have .md extension" >&2 # Allow but warn fi echo "$abs_path" } DEFAULT_DIARY="$HOME/diary.md" DIARY_FILE="${DIARY_FILE:-$DEFAULT_DIARY}" DIARY_FILE=$(validate_safe_path "$DIARY_FILE" "diary") ``` The validated path is subsequently modified without enforcing the Markdown extension: ```bash # Check if diary file exists, create if not if [ ! -f "$DIARY_FILE" ]; then echo "# 📓 ...[truncated 4451 chars]
- Remediation
- ## Remediation Suggestions 1. Restrict diary files to a dedicated canonical directory, such as `$HOME/.local/share/mini-diary/`, rather than permitting every file below the home directory. 2. Canonicalize both the target and its parent directory. For a new file, resolve the parent with `realpath` and then append a validated basename. 3. Compare canonical paths using path-component-aware string logic rather than regular expressions. For example, accept only the exact root or paths beginning with `"$allowed_root/"`. 4. Reject diary paths that do not end in `.md`; do not merely warn. 5. Reject symbolic links for diary files and synchronization destinations, or explicitly resolve them and validate the resolved destination. 6. Validate `NEXTCLOUD_SYNC_DIR` against a separately configured, canonical synchronization root. 7. Write new files atomically with restrictive permissions and avoid following links. Where supported, use secure file-descriptor operations with no-follow semantics. 8. Reject control characters, including carriage returns and newlines, in note input if each invocation is intended to create one Markdown list item. 9. Add tests for sibling-prefix paths, regex metacharacters in `HOME`, non-Markdown targets, multiline note input, and symlinked NextCloud destinations.
