Enhance QA script output with colors and better formatting
Improvements to output/reporting: - Color-coded severity levels (red=CRITICAL, yellow=HIGH, blue=MEDIUM, cyan=LOW) - Progress indicators during scan - Relative file paths (easier to read) - Scan duration timing - Smart category breakdown (only shows categories with issues, sorted by count) - Better visual hierarchy with bold headers and separators - Helpful next steps based on results - Improved footer with useful command examples - Zero issues now shows green success message Terminal output is now much easier to scan and understand at a glance while maintaining plain text format in the report file.
This commit is contained in:
+169
-45
@@ -61,6 +61,20 @@ if [ ! -d "$TOOLKIT_PATH" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Colors for output (only if terminal)
|
||||||
|
if [ -t 1 ]; then
|
||||||
|
RED='\033[0;31m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
BOLD='\033[1m'
|
||||||
|
DIM='\033[2m'
|
||||||
|
NC='\033[0m'
|
||||||
|
else
|
||||||
|
RED='' YELLOW='' BLUE='' GREEN='' CYAN='' BOLD='' DIM='' NC=''
|
||||||
|
fi
|
||||||
|
|
||||||
# Output file for easy review
|
# Output file for easy review
|
||||||
REPORT="/tmp/qa-report.txt"
|
REPORT="/tmp/qa-report.txt"
|
||||||
> "$REPORT"
|
> "$REPORT"
|
||||||
@@ -69,6 +83,18 @@ REPORT="/tmp/qa-report.txt"
|
|||||||
TEMP_COUNTS="/tmp/qa-counts.$$"
|
TEMP_COUNTS="/tmp/qa-counts.$$"
|
||||||
echo "0 0 0 0" > "$TEMP_COUNTS"
|
echo "0 0 0 0" > "$TEMP_COUNTS"
|
||||||
|
|
||||||
|
# Track check timing
|
||||||
|
START_TIME=$(date +%s)
|
||||||
|
|
||||||
|
# Progress indicator
|
||||||
|
show_progress() {
|
||||||
|
local check_num="$1"
|
||||||
|
local check_name="$2"
|
||||||
|
if [ -t 1 ] && ! $SUMMARY_MODE; then
|
||||||
|
printf "\r${DIM}[%2d/88] ${NC}%s${DIM}...${NC}" "$check_num" "$check_name"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# Helper to increment counters (avoids subshell issue)
|
# Helper to increment counters (avoids subshell issue)
|
||||||
count_issue() {
|
count_issue() {
|
||||||
local severity="$1"
|
local severity="$1"
|
||||||
@@ -3197,9 +3223,17 @@ echo ""
|
|||||||
#==============================================================================
|
#==============================================================================
|
||||||
# SUMMARY
|
# SUMMARY
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
|
# Clear progress line
|
||||||
|
if [ -t 1 ]; then
|
||||||
|
printf "\r%80s\r" " "
|
||||||
|
fi
|
||||||
|
|
||||||
read crit high med low < "$TEMP_COUNTS"
|
read crit high med low < "$TEMP_COUNTS"
|
||||||
total=$((crit + high + med + low))
|
total=$((crit + high + med + low))
|
||||||
|
END_TIME=$(date +%s)
|
||||||
|
DURATION=$((END_TIME - START_TIME))
|
||||||
|
|
||||||
|
# Write plain summary to file
|
||||||
{
|
{
|
||||||
echo "═══════════════════════════════════════════════════════════════"
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
echo "SUMMARY"
|
echo "SUMMARY"
|
||||||
@@ -3211,9 +3245,42 @@ echo " MEDIUM: $med"
|
|||||||
echo " LOW: $low"
|
echo " LOW: $low"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Files Scanned: $(find "$TOOLKIT_PATH" -name "*.sh" 2>/dev/null | wc -l)"
|
echo "Files Scanned: $(find "$TOOLKIT_PATH" -name "*.sh" 2>/dev/null | wc -l)"
|
||||||
|
echo "Scan Duration: ${DURATION}s"
|
||||||
echo "Report: $REPORT"
|
echo "Report: $REPORT"
|
||||||
echo "═══════════════════════════════════════════════════════════════"
|
echo "═══════════════════════════════════════════════════════════════"
|
||||||
} | tee -a "$REPORT"
|
} >> "$REPORT"
|
||||||
|
|
||||||
|
# Display colored summary to terminal
|
||||||
|
echo -e "${BOLD}═══════════════════════════════════════════════════════════════${NC}"
|
||||||
|
echo -e "${BOLD} QA SCAN RESULTS${NC}"
|
||||||
|
echo -e "${BOLD}═══════════════════════════════════════════════════════════════${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${BOLD}Total Issues:${NC} $total"
|
||||||
|
if [ "$crit" -gt 0 ]; then
|
||||||
|
echo -e " ${RED}${BOLD}CRITICAL:${NC} ${RED}$crit${NC} ${DIM}(must fix immediately)${NC}"
|
||||||
|
else
|
||||||
|
echo -e " ${DIM}CRITICAL: 0${NC}"
|
||||||
|
fi
|
||||||
|
if [ "$high" -gt 0 ]; then
|
||||||
|
echo -e " ${YELLOW}HIGH:${NC} ${YELLOW}$high${NC} ${DIM}(fix soon)${NC}"
|
||||||
|
else
|
||||||
|
echo -e " ${DIM}HIGH: 0${NC}"
|
||||||
|
fi
|
||||||
|
if [ "$med" -gt 0 ]; then
|
||||||
|
echo -e " ${BLUE}MEDIUM:${NC} ${BLUE}$med${NC} ${DIM}(review when possible)${NC}"
|
||||||
|
else
|
||||||
|
echo -e " ${DIM}MEDIUM: 0${NC}"
|
||||||
|
fi
|
||||||
|
if [ "$low" -gt 0 ]; then
|
||||||
|
echo -e " ${CYAN}LOW:${NC} ${CYAN}$low${NC} ${DIM}(minor issues)${NC}"
|
||||||
|
else
|
||||||
|
echo -e " ${DIM}LOW: 0${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
echo -e "${DIM}Files Scanned: $(find "$TOOLKIT_PATH" -name "*.sh" 2>/dev/null | wc -l)${NC}"
|
||||||
|
echo -e "${DIM}Scan Duration: ${DURATION}s${NC}"
|
||||||
|
echo -e "${DIM}Full Report: $REPORT${NC}"
|
||||||
|
echo -e "${BOLD}═══════════════════════════════════════════════════════════════${NC}"
|
||||||
|
|
||||||
# Summary mode: just show counts and exit
|
# Summary mode: just show counts and exit
|
||||||
if $SUMMARY_MODE; then
|
if $SUMMARY_MODE; then
|
||||||
@@ -3234,66 +3301,123 @@ if $SUMMARY_MODE; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "DETAILED BREAKDOWN BY SEVERITY:"
|
echo -e "${BOLD}DETAILED BREAKDOWN BY SEVERITY:${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Group and display by severity
|
# Group and display by severity with colors
|
||||||
echo "CRITICAL ISSUES ($crit):"
|
if [ "$crit" -gt 0 ]; then
|
||||||
grep "^CRITICAL|" "$REPORT" | while IFS='|' read -r sev file line issue; do
|
echo -e "${RED}${BOLD}CRITICAL ISSUES ($crit):${NC}"
|
||||||
printf " %s:%s - %s\n" "$file" "$line" "$issue"
|
grep "^CRITICAL|" "$REPORT" | while IFS='|' read -r sev file line issue; do
|
||||||
done
|
# Simplify file path (relative to toolkit)
|
||||||
echo ""
|
rel_file="${file#$TOOLKIT_PATH/}"
|
||||||
|
printf " ${RED}●${NC} %s:%s ${DIM}-${NC} %s\n" "$rel_file" "$line" "$issue"
|
||||||
echo "HIGH ISSUES ($high):"
|
done
|
||||||
grep "^HIGH|" "$REPORT" | head -15 | while IFS='|' read -r sev file line issue; do
|
echo ""
|
||||||
printf " %s:%s - %s\n" "$file" "$line" "$issue"
|
|
||||||
done
|
|
||||||
if [ "$high" -gt 15 ]; then
|
|
||||||
echo " ... and $((high - 15)) more (see $REPORT)"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "MEDIUM ISSUES ($med):"
|
|
||||||
grep "^MEDIUM|" "$REPORT" | head -10 | while IFS='|' read -r sev file line issue; do
|
|
||||||
printf " %s:%s - %s\n" "$file" "$line" "$issue"
|
|
||||||
done
|
|
||||||
if [ "$med" -gt 10 ]; then
|
|
||||||
echo " ... and $((med - 10)) more (see $REPORT)"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "LOW ISSUES ($low):"
|
|
||||||
grep "^LOW|" "$REPORT" | head -5 | while IFS='|' read -r sev file line issue; do
|
|
||||||
printf " %s:%s - %s\n" "$file" "$line" "$issue"
|
|
||||||
done
|
|
||||||
if [ "$low" -gt 5 ]; then
|
|
||||||
echo " ... and $((low - 5)) more (see $REPORT)"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
if [ "$high" -gt 0 ]; then
|
||||||
echo "═══════════════════════════════════════════════════════════════"
|
echo -e "${YELLOW}HIGH ISSUES ($high):${NC}"
|
||||||
echo "CATEGORY BREAKDOWN (Top Issues by Type):"
|
grep "^HIGH|" "$REPORT" | head -15 | while IFS='|' read -r sev file line issue; do
|
||||||
echo "═══════════════════════════════════════════════════════════════"
|
rel_file="${file#$TOOLKIT_PATH/}"
|
||||||
|
printf " ${YELLOW}●${NC} %s:%s ${DIM}-${NC} %s\n" "$rel_file" "$line" "$issue"
|
||||||
|
done
|
||||||
|
if [ "$high" -gt 15 ]; then
|
||||||
|
echo -e " ${DIM}... and $((high - 15)) more (see $REPORT)${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$med" -gt 0 ]; then
|
||||||
|
echo -e "${BLUE}MEDIUM ISSUES ($med):${NC}"
|
||||||
|
grep "^MEDIUM|" "$REPORT" | head -10 | while IFS='|' read -r sev file line issue; do
|
||||||
|
rel_file="${file#$TOOLKIT_PATH/}"
|
||||||
|
printf " ${BLUE}●${NC} %s:%s ${DIM}-${NC} %s\n" "$rel_file" "$line" "$issue"
|
||||||
|
done
|
||||||
|
if [ "$med" -gt 10 ]; then
|
||||||
|
echo -e " ${DIM}... and $((med - 10)) more (see $REPORT)${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$low" -gt 0 ]; then
|
||||||
|
echo -e "${CYAN}LOW ISSUES ($low):${NC}"
|
||||||
|
grep "^LOW|" "$REPORT" | head -5 | while IFS='|' read -r sev file line issue; do
|
||||||
|
rel_file="${file#$TOOLKIT_PATH/}"
|
||||||
|
printf " ${CYAN}●${NC} %s:%s ${DIM}-${NC} %s\n" "$rel_file" "$line" "$issue"
|
||||||
|
done
|
||||||
|
if [ "$low" -gt 5 ]; then
|
||||||
|
echo -e " ${DIM}... and $((low - 5)) more (see $REPORT)${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${BOLD}═══════════════════════════════════════════════════════════════${NC}"
|
||||||
|
echo -e "${BOLD}TOP ISSUES BY CATEGORY:${NC}"
|
||||||
|
echo -e "${BOLD}═══════════════════════════════════════════════════════════════${NC}"
|
||||||
|
|
||||||
|
# Create array of category counts
|
||||||
|
declare -A cat_counts
|
||||||
for tag in SQL-INJ CMD-INJ PANEL-CALL FILE-OP SECRET-LEAK RACE SOURCE RETURN NULL DEP TEMP SUBSHELL PIPE WORDSPLIT ARITH TEST REDIR TRAP ARRAY HEREDOC IF-MASK NUMCMP BG-JOB LOCALE PROC-SUB PRINTF REGEX BASHISM ESCAPE SLEEP-RACE IFS SUBSHELL-VAR TRAP-RACE PERF-LOOP PERF-CACHE PERF-READ RECURSION FD-LEAK ZOMBIE DISK-SPACE NET-TIMEOUT LOG-ROTATE CPU-LOOP HARDCODED-PATH MISSING-LIB USERDATA-ACCESS API-CHECK NO-CASE DB-PATTERN NO-USER-MGR NO-STANDALONE; do
|
for tag in SQL-INJ CMD-INJ PANEL-CALL FILE-OP SECRET-LEAK RACE SOURCE RETURN NULL DEP TEMP SUBSHELL PIPE WORDSPLIT ARITH TEST REDIR TRAP ARRAY HEREDOC IF-MASK NUMCMP BG-JOB LOCALE PROC-SUB PRINTF REGEX BASHISM ESCAPE SLEEP-RACE IFS SUBSHELL-VAR TRAP-RACE PERF-LOOP PERF-CACHE PERF-READ RECURSION FD-LEAK ZOMBIE DISK-SPACE NET-TIMEOUT LOG-ROTATE CPU-LOOP HARDCODED-PATH MISSING-LIB USERDATA-ACCESS API-CHECK NO-CASE DB-PATTERN NO-USER-MGR NO-STANDALONE; do
|
||||||
count=$(grep -c "\[$tag\]" "$REPORT" 2>/dev/null || echo 0)
|
count=$(grep -c "\[$tag\]" "$REPORT" 2>/dev/null || echo 0)
|
||||||
if [ "$count" -gt 0 ]; then
|
if [ "$count" -gt 0 ]; then
|
||||||
printf " %-12s: %d issues\n" "$tag" "$count"
|
cat_counts[$tag]=$count
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Sort and display (show top 15)
|
||||||
|
if [ ${#cat_counts[@]} -gt 0 ]; then
|
||||||
|
for tag in "${!cat_counts[@]}"; do
|
||||||
|
echo "${cat_counts[$tag]} $tag"
|
||||||
|
done | sort -rn | head -15 | while read count tag; do
|
||||||
|
# Color code based on severity keywords
|
||||||
|
if [[ "$tag" =~ (SQL-INJ|CMD-INJ|SECRET) ]]; then
|
||||||
|
printf " ${RED}%-20s${NC} %s\n" "$tag" "${CYAN}$count issues${NC}"
|
||||||
|
elif [[ "$tag" =~ (FILE-OP|RACE|PANEL) ]]; then
|
||||||
|
printf " ${YELLOW}%-20s${NC} %s\n" "$tag" "${CYAN}$count issues${NC}"
|
||||||
|
else
|
||||||
|
printf " ${DIM}%-20s${NC} %s\n" "$tag" "${CYAN}$count issues${NC}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
total_cats=${#cat_counts[@]}
|
||||||
|
if [ "$total_cats" -gt 15 ]; then
|
||||||
|
echo -e " ${DIM}... and $((total_cats - 15)) more categories (see $REPORT)${NC}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e " ${GREEN}No issues found!${NC}"
|
||||||
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Cleanup
|
# Cleanup
|
||||||
rm -f "$TEMP_COUNTS"
|
rm -f "$TEMP_COUNTS"
|
||||||
|
|
||||||
|
echo -e "${BOLD}═══════════════════════════════════════════════════════════════${NC}"
|
||||||
|
echo -e "${BOLD}NEXT STEPS:${NC}"
|
||||||
|
echo -e "${BOLD}═══════════════════════════════════════════════════════════════${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Full report saved to: $REPORT"
|
if [ "$total" -eq 0 ]; then
|
||||||
|
echo -e " ${GREEN}✓${NC} Code quality looks good!"
|
||||||
|
echo -e " ${DIM}No issues found in this scan${NC}"
|
||||||
|
elif [ "$crit" -gt 0 ]; then
|
||||||
|
echo -e " ${RED}!${NC} Fix ${RED}CRITICAL${NC} issues immediately"
|
||||||
|
echo -e " ${DIM}Use: grep '^CRITICAL' $REPORT${NC}"
|
||||||
|
elif [ "$high" -gt 0 ]; then
|
||||||
|
echo -e " ${YELLOW}!${NC} Review ${YELLOW}HIGH${NC} priority issues soon"
|
||||||
|
echo -e " ${DIM}Use: grep '^HIGH' $REPORT${NC}"
|
||||||
|
else
|
||||||
|
echo -e " ${BLUE}•${NC} Review and fix issues when possible"
|
||||||
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
echo "Quick Filter Examples:"
|
echo -e "${DIM}Full report: $REPORT${NC}"
|
||||||
echo " --quick Show CRITICAL + HIGH only (faster)"
|
echo ""
|
||||||
echo " --security Security issues only"
|
echo -e "${BOLD}Useful Commands:${NC}"
|
||||||
echo " --category SQL-INJ SQL injection issues only"
|
echo -e " ${CYAN}$0 --quick${NC} ${DIM}# Fast scan (CRITICAL + HIGH only)${NC}"
|
||||||
echo " --summary Just counts, no details"
|
echo -e " ${CYAN}$0 --security${NC} ${DIM}# Security issues only${NC}"
|
||||||
|
echo -e " ${CYAN}$0 --category SQL-INJ${NC} ${DIM}# Filter by category${NC}"
|
||||||
|
echo -e " ${CYAN}$0 --summary${NC} ${DIM}# Show counts only${NC}"
|
||||||
|
echo -e " ${CYAN}grep '^CRITICAL' $REPORT${NC} ${DIM}# View all critical issues${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${DIM}Scan completed in ${DURATION}s | Exit code: $total${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Exit code: $total"
|
|
||||||
|
|
||||||
exit $total
|
exit $total
|
||||||
|
|||||||
Reference in New Issue
Block a user