diff --git a/tools/toolkit-qa-check.sh b/tools/toolkit-qa-check.sh index 9a8698d..91f5aef 100755 --- a/tools/toolkit-qa-check.sh +++ b/tools/toolkit-qa-check.sh @@ -58,7 +58,7 @@ echo "" #============================================================================== # CHECK 1: grep -F with regex anchors (CRITICAL - causes wrong results) #============================================================================== -echo "[1/20] Checking: grep -F with regex anchors..." +echo "[1/30] Checking: grep -F with regex anchors..." { echo "## CHECK 1: grep -F with regex anchors" echo "Severity: CRITICAL" @@ -79,7 +79,7 @@ echo "" #============================================================================== # CHECK 2: SCRIPT_DIR collisions (HIGH - causes path errors) #============================================================================== -echo "[2/20] Checking: SCRIPT_DIR variable collisions..." +echo "[2/30] Checking: SCRIPT_DIR variable collisions..." { echo "## CHECK 2: SCRIPT_DIR variable collisions" echo "Severity: HIGH" @@ -99,7 +99,7 @@ echo "" #============================================================================== # CHECK 3: SYS_* variable resets (CRITICAL - breaks system detection) #============================================================================== -echo "[3/20] Checking: SYS_* variable resets..." +echo "[3/30] Checking: SYS_* variable resets..." { echo "## CHECK 3: SYS_* variable resets without protection" echo "Severity: CRITICAL" @@ -120,7 +120,7 @@ echo "" #============================================================================== # CHECK 4: Missing function exports (HIGH - functions unavailable) #============================================================================== -echo "[4/20] Checking: Missing function exports..." +echo "[4/30] Checking: Missing function exports..." { echo "## CHECK 4: Missing function exports in libraries" echo "Severity: HIGH" @@ -145,7 +145,7 @@ echo "" #============================================================================== # CHECK 5: Integer comparisons without empty checks (HIGH - causes errors) #============================================================================== -echo "[5/20] Checking: Unsafe integer comparisons (top 10)..." +echo "[5/30] Checking: Unsafe integer comparisons (top 10)..." { echo "## CHECK 5: Integer comparisons without empty checks" echo "Severity: HIGH" @@ -170,7 +170,7 @@ echo "" #============================================================================== # CHECK 6: Missing common-functions.sh (HIGH - command not found) #============================================================================== -echo "[6/20] Checking: Missing common-functions.sh..." +echo "[6/30] Checking: Missing common-functions.sh..." { echo "## CHECK 6: Missing common-functions.sh sourcing" echo "Severity: HIGH" @@ -190,7 +190,7 @@ echo "" #============================================================================== # CHECK 7: exit in libraries (HIGH - terminates parent script) #============================================================================== -echo "[7/20] Checking: exit in library files..." +echo "[7/30] Checking: exit in library files..." { echo "## CHECK 7: exit in sourced libraries" echo "Severity: HIGH" @@ -215,7 +215,7 @@ echo "" #============================================================================== # CHECK 8: bc command usage (LOW - external dependency) #============================================================================== -echo "[8/20] Checking: bc command usage..." +echo "[8/30] Checking: bc command usage..." { echo "## CHECK 8: bc command usage" echo "Severity: LOW" @@ -238,7 +238,7 @@ echo "" #============================================================================== # CHECK 9: Hardcoded /var/cpanel paths (MEDIUM - breaks multi-panel) #============================================================================== -echo "[9/20] Checking: Hardcoded /var/cpanel paths..." +echo "[9/30] Checking: Hardcoded /var/cpanel paths..." { echo "## CHECK 9: Hardcoded /var/cpanel paths" echo "Severity: MEDIUM" @@ -264,7 +264,7 @@ echo "" #============================================================================== # CHECK 10: Undefined color variables (LOW - cosmetic issue) #============================================================================== -echo "[10/20] Checking: Undefined color variables..." +echo "[10/30] Checking: Undefined color variables..." { echo "## CHECK 10: Undefined color variables" echo "Severity: LOW" @@ -289,7 +289,7 @@ echo "" #============================================================================== # CHECK 11: Bash syntax validation (CRITICAL - prevents execution) #============================================================================== -echo "[11/20] Checking: Bash syntax errors..." +echo "[11/30] Checking: Bash syntax errors..." { echo "## CHECK 11: Bash syntax validation" echo "Severity: CRITICAL" @@ -310,7 +310,7 @@ echo "" #============================================================================== # CHECK 12: Dangerous rm commands (CRITICAL - data loss risk) #============================================================================== -echo "[12/20] Checking: Dangerous rm commands..." +echo "[12/30] Checking: Dangerous rm commands..." { echo "## CHECK 12: Dangerous rm commands" echo "Severity: CRITICAL" @@ -334,7 +334,7 @@ echo "" #============================================================================== # CHECK 13: Unquoted variable expansions (HIGH - word splitting/globbing risks) #============================================================================== -echo "[13/20] Checking: Unquoted variables in dangerous contexts..." +echo "[13/30] Checking: Unquoted variables in dangerous contexts..." { echo "## CHECK 13: Unquoted variable expansions" echo "Severity: HIGH" @@ -358,7 +358,7 @@ echo "" #============================================================================== # CHECK 14: Command injection via eval (CRITICAL - arbitrary code execution) #============================================================================== -echo "[14/20] Checking: Command injection risks..." +echo "[14/30] Checking: Command injection risks..." { echo "## CHECK 14: Command injection via eval" echo "Severity: CRITICAL" @@ -379,7 +379,7 @@ echo "" #============================================================================== # CHECK 15: Temp file security (MEDIUM - race conditions/predictable names) #============================================================================== -echo "[15/20] Checking: Temp file security..." +echo "[15/30] Checking: Temp file security..." { echo "## CHECK 15: Insecure temp file creation" echo "Severity: MEDIUM" @@ -402,7 +402,7 @@ echo "" #============================================================================== # CHECK 16: TODO/FIXME/HACK markers (LOW - technical debt tracking) #============================================================================== -echo "[16/20] Checking: Technical debt markers..." +echo "[16/30] Checking: Technical debt markers..." { echo "## CHECK 16: TODO/FIXME/HACK comments" echo "Severity: LOW" @@ -426,7 +426,7 @@ echo "" #============================================================================== # CHECK 17: Duplicate function definitions (MEDIUM - causes conflicts) #============================================================================== -echo "[17/20] Checking: Duplicate function definitions..." +echo "[17/30] Checking: Duplicate function definitions..." { echo "## CHECK 17: Duplicate function definitions" echo "Severity: MEDIUM" @@ -452,7 +452,7 @@ echo "" #============================================================================== # CHECK 18: Missing input validation (HIGH - security/reliability risk) #============================================================================== -echo "[18/20] Checking: Missing input validation..." +echo "[18/30] Checking: Missing input validation..." { echo "## CHECK 18: Functions without parameter validation" echo "Severity: HIGH" @@ -486,7 +486,7 @@ echo "" #============================================================================== # CHECK 19: Long functions (MEDIUM - maintainability issue) #============================================================================== -echo "[19/20] Checking: Overly long functions..." +echo "[19/30] Checking: Overly long functions..." { echo "## CHECK 19: Long functions (>100 lines)" echo "Severity: MEDIUM" @@ -531,7 +531,7 @@ echo "" #============================================================================== # CHECK 20: ShellCheck integration (if available) #============================================================================== -echo "[20/20] Checking: ShellCheck warnings (if available)..." +echo "[20/30] Checking: ShellCheck warnings (if available)..." { echo "## CHECK 20: ShellCheck static analysis" echo "Severity: VARIES" @@ -564,6 +564,274 @@ fi echo "" } >> "$REPORT" +#============================================================================== +# CHECK 21: Using [ ] instead of [[ ]] (MEDIUM - less safe) +#============================================================================== +echo "[21/30] Checking: Single bracket conditionals..." +{ +echo "## CHECK 21: Using [ ] instead of [[ ]]" +echo "Severity: MEDIUM" +echo "Issue: Single brackets don't handle empty vars/special chars safely" +echo "" + +count=0 +while IFS=: read -r file line_num line_content; do + # Check for [ with string comparisons or variable tests + if echo "$line_content" | grep -qE '\[\s+[^]]*(\$[a-zA-Z_]|==|!=)[^]]*\]'; then + # Skip if it's already [[ ]] or a comment + if ! echo "$line_content" | grep -qE '^\s*#|\[\['; then + echo "MEDIUM|$file|$line_num|Using [ ] instead of safer [[ ]]" + count_issue "MEDIUM" + ((count++)) + [ "$count" -ge 10 ] && break + fi + fi +done < <(grep -rn '\[\s' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null) + +echo "Found: $count issues (showing first 10)" +echo "" +} >> "$REPORT" + +#============================================================================== +# CHECK 22: Looping over ls output (HIGH - fatally flawed pattern) +#============================================================================== +echo "[22/30] Checking: Loops over ls output..." +{ +echo "## CHECK 22: Looping over ls output" +echo "Severity: HIGH" +echo "Issue: for f in \$(ls) breaks with spaces/special chars" +echo "" + +while IFS=: read -r file line_num line_content; do + if ! echo "$line_content" | grep -q '^\s*#'; then + echo "HIGH|$file|$line_num|Looping over ls output (use glob or find -print0)" + count_issue "HIGH" + fi +done < <(grep -rnE 'for\s+\w+\s+in\s+\$\(ls' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null | head -10) + +echo "" +} >> "$REPORT" + +#============================================================================== +# CHECK 23: Missing set -euo pipefail (MEDIUM - silent failures) +#============================================================================== +echo "[23/30] Checking: Missing error handling flags..." +{ +echo "## CHECK 23: Missing set -euo pipefail" +echo "Severity: MEDIUM" +echo "Issue: Scripts continue after errors, unset vars expand to empty" +echo "" + +count=0 +while read -r file; do + # Skip library files (they're sourced, not executed) + if [[ "$file" == */lib/* ]]; then + continue + fi + + # Check for shebang (executable script) + if head -1 "$file" 2>/dev/null | grep -q '^#!/bin/bash'; then + # Check if it has any error handling + if ! grep -q 'set -[euo]' "$file" 2>/dev/null; then + echo "MEDIUM|$file|N/A|Missing set -e/-u/-o pipefail (consider 'set -euo pipefail')" + count_issue "MEDIUM" + ((count++)) + [ "$count" -ge 10 ] && break + fi + fi +done < <(find "$TOOLKIT_PATH/modules" "$TOOLKIT_PATH/tools" -name "*.sh" 2>/dev/null) + +echo "Found: $count scripts without error handling" +echo "" +} >> "$REPORT" + +#============================================================================== +# CHECK 24: Unused variables (LOW - dead code) +#============================================================================== +echo "[24/30] Checking: Unused variables..." +{ +echo "## CHECK 24: Unused variables" +echo "Severity: LOW" +echo "Issue: Variables declared but never used (AI code smell)" +echo "" + +count=0 +while read -r file; do + # Find all variable assignments + while IFS=: read -r line_num var_line; do + var_name=$(echo "$var_line" | grep -oE '^[[:space:]]*(local[[:space:]]+)?([a-zA-Z_][a-zA-Z0-9_]*)=' | sed 's/local //; s/=//') + if [ -n "$var_name" ]; then + # Check if variable is used anywhere after declaration + if ! grep -q "\$$var_name\b" "$file" 2>/dev/null; then + echo "LOW|$file|$line_num|Unused variable: $var_name" + count_issue "LOW" + ((count++)) + [ "$count" -ge 15 ] && break 2 + fi + fi + done < <(grep -n '^\s*\(local \)\?[a-zA-Z_][a-zA-Z0-9_]*=' "$file" 2>/dev/null | head -20) +done < <(find "$TOOLKIT_PATH" -name "*.sh" -not -name "toolkit-qa-check.sh" 2>/dev/null | head -5) + +echo "Note: Checked first 5 files, showing first 15 issues" +echo "" +} >> "$REPORT" + +#============================================================================== +# CHECK 25: Backticks instead of $() (LOW - deprecated syntax) +#============================================================================== +echo "[25/30] Checking: Deprecated backticks..." +{ +echo "## CHECK 25: Using backticks instead of \$()" +echo "Severity: LOW" +echo "Issue: Backticks are deprecated, harder to nest" +echo "" + +while IFS=: read -r file line_num line_content; do + if ! echo "$line_content" | grep -q '^\s*#'; then + echo "LOW|$file|$line_num|Uses backticks (use \$(...) instead)" + count_issue "LOW" + fi +done < <(grep -rn '`[^`]*`' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null | head -10) + +echo "" +} >> "$REPORT" + +#============================================================================== +# CHECK 26: Missing or wrong shebang (HIGH - execution issues) +#============================================================================== +echo "[26/30] Checking: Shebang issues..." +{ +echo "## CHECK 26: Missing or incorrect shebang" +echo "Severity: HIGH" +echo "Issue: Script won't execute correctly without proper shebang" +echo "" + +while read -r file; do + # Skip library files (sourced, not executed) + if [[ "$file" == */lib/* ]]; then + continue + fi + + first_line=$(head -1 "$file" 2>/dev/null) + + # Check if missing shebang + if [ ! "$first_line" = "#!/bin/bash" ] && [ ! "$first_line" = "#!/usr/bin/env bash" ]; then + if [ "${first_line:0:2}" != "#!" ]; then + echo "HIGH|$file|1|Missing shebang (add #!/bin/bash)" + count_issue "HIGH" + else + echo "MEDIUM|$file|1|Non-standard shebang: $first_line" + count_issue "MEDIUM" + fi + fi +done < <(find "$TOOLKIT_PATH/modules" "$TOOLKIT_PATH/tools" -name "*.sh" 2>/dev/null | head -20) + +echo "" +} >> "$REPORT" + +#============================================================================== +# CHECK 27: Not checking command exit status (MEDIUM - silent failures) +#============================================================================== +echo "[27/30] Checking: Unchecked critical commands..." +{ +echo "## CHECK 27: Critical commands without exit status checks" +echo "Severity: MEDIUM" +echo "Issue: Commands that can fail should be checked" +echo "" + +count=0 +while IFS=: read -r file line_num line_content; do + # Check for critical commands without || or && or if checks + if echo "$line_content" | grep -qE '^\s*(curl|wget|rsync|mysql|ssh|git)\s' && \ + ! echo "$line_content" | grep -qE '(\|\||&&|if\s)'; then + # Skip comments + if ! echo "$line_content" | grep -q '^\s*#'; then + cmd=$(echo "$line_content" | awk '{print $1}') + echo "MEDIUM|$file|$line_num|$cmd command without exit status check" + count_issue "MEDIUM" + ((count++)) + [ "$count" -ge 10 ] && break + fi + fi +done < <(grep -rnE '^\s*(curl|wget|rsync|mysql|ssh|git)\s' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null) + +echo "Found: $count unchecked commands (showing first 10)" +echo "" +} >> "$REPORT" + +#============================================================================== +# CHECK 28: Incorrect string/number comparison (HIGH - type confusion) +#============================================================================== +echo "[28/30] Checking: Type confusion in comparisons..." +{ +echo "## CHECK 28: Using wrong comparison operators" +echo "Severity: HIGH" +echo "Issue: -eq for strings or = for numbers causes bugs" +echo "" + +count=0 +# Check for -eq with likely string variables +while IFS=: read -r file line_num line_content; do + if echo "$line_content" | grep -qE '\$[A-Z_]*[a-z][A-Za-z_]*(name|user|status|type|mode|method)\s+-eq\s'; then + echo "HIGH|$file|$line_num|Using -eq for likely string comparison (use = or ==)" + count_issue "HIGH" + ((count++)) + [ "$count" -ge 5 ] && break + fi +done < <(grep -rnE '\-eq\s' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null) + +echo "Found: $count type confusion issues (showing first 5)" +echo "" +} >> "$REPORT" + +#============================================================================== +# CHECK 29: Unsafe array iteration (MEDIUM - word splitting) +#============================================================================== +echo "[29/30] Checking: Unsafe array expansions..." +{ +echo "## CHECK 29: Array iteration without quotes" +echo "Severity: MEDIUM" +echo "Issue: Use \"\${array[@]}\" not \${array[@]} or \$array" +echo "" + +count=0 +while IFS=: read -r file line_num line_content; do + # Check for unquoted array expansions + if echo "$line_content" | grep -qE 'for\s+\w+\s+in\s+\$\{[^}]+\[@\]\}' && \ + ! echo "$line_content" | grep -q '"\${'; then + echo "MEDIUM|$file|$line_num|Unquoted array expansion (causes word splitting)" + count_issue "MEDIUM" + ((count++)) + [ "$count" -ge 10 ] && break + fi +done < <(grep -rnE 'for\s+\w+\s+in\s+\$\{.*\[@\]' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null) + +echo "Found: $count unsafe array iterations" +echo "" +} >> "$REPORT" + +#============================================================================== +# CHECK 30: Hardcoded credentials or secrets (CRITICAL - security) +#============================================================================== +echo "[30/30] Checking: Hardcoded credentials..." +{ +echo "## CHECK 30: Hardcoded passwords/API keys" +echo "Severity: CRITICAL" +echo "Issue: Credentials in code = major security vulnerability" +echo "" + +while IFS=: read -r file line_num line_content; do + # Look for suspicious patterns + if echo "$line_content" | grep -qiE '(password|passwd|pwd|api_key|apikey|secret|token|auth)=["'"'"'][^"'"'"']+["'"'"']' && \ + ! echo "$line_content" | grep -qE '^\s*#||REDACTED|YOUR_|ENTER_|example'; then + echo "CRITICAL|$file|$line_num|Possible hardcoded credential detected" + count_issue "CRITICAL" + fi +done < <(grep -rniE '(password|passwd|api_key|apikey|secret|token)=' "$TOOLKIT_PATH" --include="*.sh" --exclude="toolkit-qa-check.sh" 2>/dev/null | head -10) + +echo "" +} >> "$REPORT" + #============================================================================== # PERFORMANCE CHECKS (INFO level - not counted as issues) #==============================================================================