T09 · Insecure Skill Coding Practices
- Location
new-piece.sh:5- Finding
Path Traversal Through Unvalidated Workspace Identifiers
- Content
View full analysis
}" TYPE="${2:?Types: article, email, tweet, doc, book, other}" TITLE="${3:?Provide a title}" # Generate ID: type-YYYYMMDD-HHMMSS ID="${TYPE}-$(date +%Y%m%d-%H%M%S)" PIECE_DIR="$WORKSPACE/pieces/$ID" mkdir -p "$PIECE_DIR" ``` `edit.sh:5-14`: ```bash WORKSPACE="${1:?Usage: edit.sh <workspace> <piece-id> <new-content-file>}" PIECE_ID="${2:?Provide piece ID}" NEW_CONTENT="${3:?Provide path to new content file}" PIECE_DIR="$WORKSPACE/pieces/$PIECE_ID" CONTENT_FILE="$PIECE_DIR/content.md" VERSION_DIR="$WORKSPACE/versions/$PIECE_ID" [[ -d "$PIECE_DIR" ]] || { echo "❌ Piece not found: $PIECE_ID"; exit 1; } [[ -f "$NEW_CONTENT" ]] || { echo "❌ New content file not found: $NEW_CONTENT"; exit 1; } ``` `restore.sh:15-27`: ```bash # Find version file VERSION_FILE=$(ls -1 "$VERSION_DIR" 2>/dev/null | grep "^${VERSION}_" | head -1) [[ -n "$VERSION_FILE" ]] || { echo "❌ Version not found: $VERSION"; exit 1; } FULL_PATH="$VERSION_DIR/$VERSION_FILE" # Backup current before restore (meta-version) TIMESTAMP=$(date +%Y%m%d-%H%M%S) BACKUP_FILE="$VERSION_DIR/pre-restore_${TIMESTAMP}.md" cp "$CONTENT_FILE" "$BACKUP_FILE" # Restore cp "$FULL_PATH" "$CONTENT_FILE" ``` `cleanup.sh:36-40`: ```bash # Delete oldest versions ls -1t "$VERSION_DIR" | tail -n "$DELETE" | while read f; do rm "$VERSION_DIR/$f" echo "🗑️ Deleted: $f" done ``` ### Technical Analysis The scripts concatenate caller-controlled values such as `TYPE`, `PIECE_ID`, and `VERSION` into filesystem paths without validating them as single, safe path components. Shell quoting prevents word splitting and wildcard expans ...[truncated 2425 chars]- Remediation
View remediation
&2 exit 1 } [[ "$value" != "." && "$value" != ".." ]] || exit 1 } ``` 2. Restrict `TYPE` to the documented values: ```bash case "$TYPE" in article|email|tweet|doc|book|other) ;; *) echo "Unsupported piece type: $TYPE" >&2 exit 1 ;; esac ``` 3. Canonicalize the workspace and destination with `realpath` or an equivalent platform-safe mechanism. Verify that each resolved destination remains under the required base directory before reading, writing, or deleting: ```bash BASE_DIR="$(realpath "$WORKSPACE/pieces")" TARGET_DIR="$(realpath -m "$BASE_DIR/$PIECE_ID")" case "$TARGET_DIR/" in "$BASE_DIR"/*) ;; *) echo "Target escapes the pieces directory" >&2 exit 1 ;; esac ``` 4. Apply equivalent containment checks independently to `pieces`, `versions`, `audits`, and `research`. 5. Avoid using `ls` output as a file-processing interface. Enumerate files with `find` using constrained paths and null-delimited output. 6. Match requested versions literally rather than interpolating untrusted input into a regular expression. Validate versions with a strict pattern such as `^v[0-9]+$`, then select the expected filename safely. 7. Before cleanup, display the canonical directory and every canonical deletion target. Reject symlinks and targets that do not remain within the expected version directory. ]]>
